40 bool tetgenio::load_node_call(FILE* infile,
int markers,
int uvflag,
43 char inputline[INPUTLINESIZE];
46 int firstnode, currentmarker;
47 int index, attribindex;
51 pointlist =
new REAL[numberofpoints * 3];
52 if (pointlist == (REAL *) NULL) {
53 terminatetetgen(NULL, 1);
55 if (numberofpointattributes > 0) {
56 pointattributelist =
new REAL[numberofpoints * numberofpointattributes];
57 if (pointattributelist == (REAL *) NULL) {
58 terminatetetgen(NULL, 1);
62 pointmarkerlist =
new int[numberofpoints];
63 if (pointmarkerlist == (
int *) NULL) {
64 terminatetetgen(NULL, 1);
68 pointparamlist =
new pointparam[numberofpoints];
69 if (pointparamlist == NULL) {
70 terminatetetgen(NULL, 1);
77 for (i = 0; i < numberofpoints; i++) {
78 stringptr = readnumberline(inputline, infile, infilename);
81 firstnode = (int) strtol (stringptr, &stringptr, 0);
82 if ((firstnode == 0) || (firstnode == 1)) {
83 firstnumber = firstnode;
86 stringptr = findnextnumber(stringptr);
88 if (*stringptr ==
'\0') {
89 printf(
"Error: Point %d has no x coordinate.\n", firstnumber + i);
92 x = (REAL) strtod(stringptr, &stringptr);
93 stringptr = findnextnumber(stringptr);
94 if (*stringptr ==
'\0') {
95 printf(
"Error: Point %d has no y coordinate.\n", firstnumber + i);
98 y = (REAL) strtod(stringptr, &stringptr);
100 stringptr = findnextnumber(stringptr);
101 if (*stringptr ==
'\0') {
102 printf(
"Error: Point %d has no z coordinate.\n", firstnumber + i);
105 z = (REAL) strtod(stringptr, &stringptr);
109 pointlist[index++] = x;
110 pointlist[index++] = y;
111 pointlist[index++] = z;
113 for (j = 0; j < numberofpointattributes; j++) {
114 stringptr = findnextnumber(stringptr);
115 if (*stringptr ==
'\0') {
118 attrib = (REAL) strtod(stringptr, &stringptr);
120 pointattributelist[attribindex++] = attrib;
124 stringptr = findnextnumber(stringptr);
125 if (*stringptr ==
'\0') {
128 currentmarker = (int) strtol (stringptr, &stringptr, 0);
130 pointmarkerlist[i] = currentmarker;
134 stringptr = findnextnumber(stringptr);
135 if (*stringptr ==
'\0') {
136 printf(
"Error: Point %d has no uv[0].\n", firstnumber + i);
139 pointparamlist[i].uv[0] = (REAL) strtod(stringptr, &stringptr);
140 stringptr = findnextnumber(stringptr);
141 if (*stringptr ==
'\0') {
142 printf(
"Error: Point %d has no uv[1].\n", firstnumber + i);
145 pointparamlist[i].uv[1] = (REAL) strtod(stringptr, &stringptr);
146 stringptr = findnextnumber(stringptr);
147 if (*stringptr ==
'\0') {
148 printf(
"Error: Point %d has no tag.\n", firstnumber + i);
151 pointparamlist[i].tag = (int) strtol (stringptr, &stringptr, 0);
152 stringptr = findnextnumber(stringptr);
153 if (*stringptr ==
'\0') {
154 printf(
"Error: Point %d has no type.\n", firstnumber + i);
157 pointparamlist[i].type = (int) strtol (stringptr, &stringptr, 0);
158 if ((pointparamlist[i].type < 0) || (pointparamlist[i].type > 2)) {
159 printf(
"Error: Point %d has an invalid type.\n", firstnumber + i);
164 if (i < numberofpoints) {
167 pointlist = (REAL *) NULL;
169 delete [] pointmarkerlist;
170 pointmarkerlist = (
int *) NULL;
172 if (numberofpointattributes > 0) {
173 delete [] pointattributelist;
174 pointattributelist = (REAL *) NULL;
177 delete [] pointparamlist;
178 pointparamlist = NULL;
192 bool tetgenio::load_node(
const char* filebasename)
195 char innodefilename[FILENAMESIZE];
196 char inputline[INPUTLINESIZE];
203 strcpy(innodefilename, filebasename);
204 strcat(innodefilename,
".node");
207 infile = fopen(innodefilename,
"r");
208 if (infile == (FILE *) NULL) {
209 printf(
" Cannot access file %s.\n", innodefilename);
212 printf(
"Opening %s.\n", innodefilename);
216 numberofpointattributes = 0;
221 stringptr = readnumberline(inputline, infile, innodefilename);
223 stringptr = strstr(inputline,
"rbox");
224 if (stringptr == NULL) {
227 stringptr = inputline;
228 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
229 stringptr = findnextnumber(stringptr);
230 if (*stringptr !=
'\0') {
231 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
233 stringptr = findnextnumber(stringptr);
234 if (*stringptr !=
'\0') {
235 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
237 stringptr = findnextnumber(stringptr);
238 if (*stringptr !=
'\0') {
239 markers = (int) strtol (stringptr, &stringptr, 0);
241 stringptr = findnextnumber(stringptr);
242 if (*stringptr !=
'\0') {
243 uvflag = (int) strtol (stringptr, &stringptr, 0);
247 stringptr = inputline;
249 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
251 stringptr = readnumberline(inputline, infile, innodefilename);
252 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
258 okflag = load_node_call(infile, markers, uvflag, innodefilename);
270 bool tetgenio::load_edge(
const char* filebasename)
273 char inedgefilename[FILENAMESIZE];
274 char inputline[INPUTLINESIZE];
280 strcpy(inedgefilename, filebasename);
281 strcat(inedgefilename,
".edge");
283 infile = fopen(inedgefilename,
"r");
284 if (infile != (FILE *) NULL) {
285 printf(
"Opening %s.\n", inedgefilename);
292 stringptr = readnumberline(inputline, infile, inedgefilename);
293 numberofedges = (int) strtol (stringptr, &stringptr, 0);
294 if (numberofedges > 0) {
295 edgelist =
new int[numberofedges * 2];
296 if (edgelist == (
int *) NULL) {
297 terminatetetgen(NULL, 1);
299 stringptr = findnextnumber(stringptr);
300 if (*stringptr ==
'\0') {
303 markers = (int) strtol (stringptr, &stringptr, 0);
306 edgemarkerlist =
new int[numberofedges];
312 for (i = 0; i < numberofedges; i++) {
314 stringptr = readnumberline(inputline, infile, inedgefilename);
315 for (j = 0; j < 2; j++) {
316 stringptr = findnextnumber(stringptr);
317 if (*stringptr ==
'\0') {
318 printf(
"Error: Edge %d is missing vertex %d in %s.\n",
319 i + firstnumber, j + 1, inedgefilename);
320 terminatetetgen(NULL, 1);
322 corner = (int) strtol(stringptr, &stringptr, 0);
323 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
324 printf(
"Error: Edge %d has an invalid vertex index.\n",
326 terminatetetgen(NULL, 1);
328 edgelist[index++] = corner;
330 if (numberofcorners == 10) {
332 stringptr = findnextnumber(stringptr);
336 stringptr = findnextnumber(stringptr);
337 edgemarkerlist[i] = (int) strtol(stringptr, &stringptr, 0);
351 bool tetgenio::load_face(
const char* filebasename)
354 char infilename[FILENAMESIZE];
355 char inputline[INPUTLINESIZE];
362 strcpy(infilename, filebasename);
363 strcat(infilename,
".face");
365 infile = fopen(infilename,
"r");
366 if (infile != (FILE *) NULL) {
367 printf(
"Opening %s.\n", infilename);
373 stringptr = readnumberline(inputline, infile, infilename);
374 numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
375 stringptr = findnextnumber(stringptr);
378 stringptr = findnextnumber(stringptr);
380 if (*stringptr ==
'\0') {
383 markers = (int) strtol (stringptr, &stringptr, 0);
385 if (numberoftrifaces > 0) {
386 trifacelist =
new int[numberoftrifaces * 3];
387 if (trifacelist == (
int *) NULL) {
388 terminatetetgen(NULL, 1);
391 trifacemarkerlist =
new int[numberoftrifaces];
392 if (trifacemarkerlist == (
int *) NULL) {
393 terminatetetgen(NULL, 1);
400 for (i = 0; i < numberoftrifaces; i++) {
402 stringptr = readnumberline(inputline, infile, infilename);
403 for (j = 0; j < 3; j++) {
404 stringptr = findnextnumber(stringptr);
405 if (*stringptr ==
'\0') {
406 printf(
"Error: Face %d is missing vertex %d in %s.\n",
407 i + firstnumber, j + 1, infilename);
408 terminatetetgen(NULL, 1);
410 corner = (int) strtol(stringptr, &stringptr, 0);
411 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
412 printf(
"Error: Face %d has an invalid vertex index.\n",
414 terminatetetgen(NULL, 1);
416 trifacelist[index++] = corner;
418 if (numberofcorners == 10) {
420 for (j = 0; j < 3; j++) {
421 stringptr = findnextnumber(stringptr);
426 stringptr = findnextnumber(stringptr);
427 if (*stringptr ==
'\0') {
430 attrib = (REAL) strtod(stringptr, &stringptr);
432 trifacemarkerlist[i] = (int) attrib;
447 bool tetgenio::load_tet(
const char* filebasename)
450 char infilename[FILENAMESIZE];
451 char inputline[INPUTLINESIZE];
455 int index, attribindex;
458 strcpy(infilename, filebasename);
459 strcat(infilename,
".ele");
461 infile = fopen(infilename,
"r");
462 if (infile != (FILE *) NULL) {
463 printf(
"Opening %s.\n", infilename);
470 stringptr = readnumberline(inputline, infile, infilename);
471 numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
472 if (numberoftetrahedra <= 0) {
473 printf(
"Error: Invalid number of tetrahedra.\n");
477 stringptr = findnextnumber(stringptr);
478 if (*stringptr ==
'\0') {
481 numberofcorners = (int) strtol(stringptr, &stringptr, 0);
483 stringptr = findnextnumber(stringptr);
484 if (*stringptr ==
'\0') {
485 numberoftetrahedronattributes = 0;
487 numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
489 if (numberofcorners != 4 && numberofcorners != 10) {
490 printf(
"Error: Wrong number of corners %d (should be 4 or 10).\n",
497 tetrahedronlist =
new int[numberoftetrahedra * numberofcorners];
498 if (tetrahedronlist == (
int *) NULL) {
499 terminatetetgen(NULL, 1);
502 if (numberoftetrahedronattributes > 0) {
503 tetrahedronattributelist =
new REAL[numberoftetrahedra *
504 numberoftetrahedronattributes];
505 if (tetrahedronattributelist == (REAL *) NULL) {
506 terminatetetgen(NULL, 1);
513 for (i = 0; i < numberoftetrahedra; i++) {
515 stringptr = readnumberline(inputline, infile, infilename);
516 for (j = 0; j < numberofcorners; j++) {
517 stringptr = findnextnumber(stringptr);
518 if (*stringptr ==
'\0') {
519 printf(
"Error: Tetrahedron %d is missing vertex %d in %s.\n",
520 i + firstnumber, j + 1, infilename);
521 terminatetetgen(NULL, 1);
523 corner = (int) strtol(stringptr, &stringptr, 0);
524 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
525 printf(
"Error: Tetrahedron %d has an invalid vertex index.\n",
527 terminatetetgen(NULL, 1);
529 tetrahedronlist[index++] = corner;
532 for (j = 0; j < numberoftetrahedronattributes; j++) {
533 stringptr = findnextnumber(stringptr);
534 if (*stringptr ==
'\0') {
537 attrib = (REAL) strtod(stringptr, &stringptr);
539 tetrahedronattributelist[attribindex++] = attrib;
554 bool tetgenio::load_vol(
const char* filebasename)
557 char inelefilename[FILENAMESIZE];
558 char infilename[FILENAMESIZE];
559 char inputline[INPUTLINESIZE];
565 strcpy(infilename, filebasename);
566 strcat(infilename,
".vol");
568 infile = fopen(infilename,
"r");
569 if (infile != (FILE *) NULL) {
570 printf(
"Opening %s.\n", infilename);
576 stringptr = readnumberline(inputline, infile, infilename);
577 volelements = (int) strtol (stringptr, &stringptr, 0);
578 if (volelements != numberoftetrahedra) {
579 strcpy(inelefilename, filebasename);
580 strcat(infilename,
".ele");
581 printf(
"Warning: %s and %s disagree on number of tetrahedra.\n",
582 inelefilename, infilename);
587 tetrahedronvolumelist =
new REAL[volelements];
588 if (tetrahedronvolumelist == (REAL *) NULL) {
589 terminatetetgen(NULL, 1);
593 for (i = 0; i < volelements; i++) {
594 stringptr = readnumberline(inputline, infile, infilename);
595 stringptr = findnextnumber(stringptr);
596 if (*stringptr ==
'\0') {
599 volume = (REAL) strtod(stringptr, &stringptr);
601 tetrahedronvolumelist[i] = volume;
616 bool tetgenio::load_var(
const char* filebasename)
619 char varfilename[FILENAMESIZE];
620 char inputline[INPUTLINESIZE];
626 strcpy(varfilename, filebasename);
627 strcat(varfilename,
".var");
628 infile = fopen(varfilename,
"r");
629 if (infile != (FILE *) NULL) {
630 printf(
"Opening %s.\n", varfilename);
636 stringptr = readnumberline(inputline, infile, varfilename);
637 if (stringptr == NULL) {
642 if (*stringptr !=
'\0') {
643 numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
645 numberoffacetconstraints = 0;
647 if (numberoffacetconstraints > 0) {
649 facetconstraintlist =
new REAL[numberoffacetconstraints * 2];
651 for (i = 0; i < numberoffacetconstraints; i++) {
652 stringptr = readnumberline(inputline, infile, varfilename);
653 stringptr = findnextnumber(stringptr);
654 if (*stringptr ==
'\0') {
655 printf(
"Error: facet constraint %d has no facet marker.\n",
659 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
661 stringptr = findnextnumber(stringptr);
662 if (*stringptr ==
'\0') {
663 printf(
"Error: facet constraint %d has no maximum area bound.\n",
667 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
670 if (i < numberoffacetconstraints) {
678 stringptr = readnumberline(inputline, infile, varfilename);
679 if (stringptr == NULL) {
684 if (*stringptr !=
'\0') {
685 numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
687 numberofsegmentconstraints = 0;
689 if (numberofsegmentconstraints > 0) {
691 segmentconstraintlist =
new REAL[numberofsegmentconstraints * 3];
693 for (i = 0; i < numberofsegmentconstraints; i++) {
694 stringptr = readnumberline(inputline, infile, varfilename);
695 stringptr = findnextnumber(stringptr);
696 if (*stringptr ==
'\0') {
697 printf(
"Error: segment constraint %d has no frist endpoint.\n",
701 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
703 stringptr = findnextnumber(stringptr);
704 if (*stringptr ==
'\0') {
705 printf(
"Error: segment constraint %d has no second endpoint.\n",
709 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
711 stringptr = findnextnumber(stringptr);
712 if (*stringptr ==
'\0') {
713 printf(
"Error: segment constraint %d has no maximum length bound.\n",
717 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
720 if (i < numberofsegmentconstraints) {
737 bool tetgenio::load_mtr(
const char* filebasename)
740 char mtrfilename[FILENAMESIZE];
741 char inputline[INPUTLINESIZE];
748 strcpy(mtrfilename, filebasename);
749 strcat(mtrfilename,
".mtr");
750 infile = fopen(mtrfilename,
"r");
751 if (infile != (FILE *) NULL) {
752 printf(
"Opening %s.\n", mtrfilename);
758 stringptr = readnumberline(inputline, infile, mtrfilename);
759 ptnum = (int) strtol (stringptr, &stringptr, 0);
760 if (ptnum != numberofpoints) {
761 printf(
" !! Point numbers are not equal. Ignored.\n");
766 stringptr = findnextnumber(stringptr);
767 if (*stringptr !=
'\0') {
768 numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
770 if ((numberofpointmtrs != 1) && (numberofpointmtrs != 3) &&
771 (numberofpointmtrs != 6)) {
773 numberofpointmtrs = 0;
774 printf(
" !! Metric size does not match (1, 3, or 6). Ignored.\n");
780 pointmtrlist =
new REAL[numberofpoints * numberofpointmtrs];
781 if (pointmtrlist == (REAL *) NULL) {
782 terminatetetgen(NULL, 1);
785 for (i = 0; i < numberofpoints; i++) {
787 stringptr = readnumberline(inputline, infile, mtrfilename);
788 for (j = 0; j < numberofpointmtrs; j++) {
789 if (*stringptr ==
'\0') {
790 printf(
"Error: Metric %d is missing value #%d in %s.\n",
791 i + firstnumber, j + 1, mtrfilename);
792 terminatetetgen(NULL, 1);
794 mtr = (REAL) strtod(stringptr, &stringptr);
795 pointmtrlist[mtrindex++] = mtr;
796 stringptr = findnextnumber(stringptr);
810 bool tetgenio::load_poly(
const char* filebasename)
813 char inpolyfilename[FILENAMESIZE];
814 char insmeshfilename[FILENAMESIZE];
815 char inputline[INPUTLINESIZE];
816 char *stringptr, *infilename;
817 int smesh, markers, uvflag, currentmarker;
822 strcpy(inpolyfilename, filebasename);
823 strcpy(insmeshfilename, filebasename);
824 strcat(inpolyfilename,
".poly");
825 strcat(insmeshfilename,
".smesh");
830 infile = fopen(inpolyfilename,
"r");
831 if (infile == (FILE *) NULL) {
833 infile = fopen(insmeshfilename,
"r");
834 if (infile == (FILE *) NULL) {
835 printf(
" Cannot access file %s and %s.\n",
836 inpolyfilename, insmeshfilename);
839 printf(
"Opening %s.\n", insmeshfilename);
840 infilename = insmeshfilename;
844 printf(
"Opening %s.\n", inpolyfilename);
845 infilename = inpolyfilename;
850 numberofpointattributes = 0;
856 stringptr = readnumberline(inputline, infile, infilename);
857 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
858 stringptr = findnextnumber(stringptr);
859 if (*stringptr !=
'\0') {
860 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
862 stringptr = findnextnumber(stringptr);
863 if (*stringptr !=
'\0') {
864 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
866 stringptr = findnextnumber(stringptr);
867 if (*stringptr !=
'\0') {
868 markers = (int) strtol (stringptr, &stringptr, 0);
870 if (*stringptr !=
'\0') {
871 uvflag = (int) strtol (stringptr, &stringptr, 0);
874 if (numberofpoints > 0) {
876 if (!load_node_call(infile, markers, uvflag, infilename)) {
883 if (!load_node(filebasename)) {
889 if ((mesh_dim != 3) && (mesh_dim != 2)) {
890 printf(
"Input error: TetGen only works for 2D & 3D point sets.\n");
894 if (numberofpoints < (mesh_dim + 1)) {
895 printf(
"Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
906 stringptr = readnumberline(inputline, infile, infilename);
907 if (stringptr == NULL) {
912 numberoffacets = (int) strtol (stringptr, &stringptr, 0);
913 if (numberoffacets <= 0) {
918 stringptr = findnextnumber(stringptr);
919 if (*stringptr ==
'\0') {
922 markers = (int) strtol (stringptr, &stringptr, 0);
926 facetlist =
new facet[numberoffacets];
928 facetmarkerlist =
new int[numberoffacets];
934 for (i = 1; i <= numberoffacets; i++) {
935 f = &(facetlist[i - 1]);
937 f->numberofholes = 0;
940 stringptr = readnumberline(inputline, infile, infilename);
941 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
942 stringptr = findnextnumber(stringptr);
943 if (*stringptr !=
'\0') {
944 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
946 stringptr = findnextnumber(stringptr);
947 if (*stringptr !=
'\0') {
948 currentmarker = (int) strtol(stringptr, &stringptr, 0);
954 facetmarkerlist[i - 1] = currentmarker;
957 if (f->numberofpolygons <= 0) {
958 printf(
"Error: Wrong number of polygon in %d facet.\n", i);
962 f->polygonlist =
new polygon[f->numberofpolygons];
964 for (j = 1; j <= f->numberofpolygons; j++) {
965 p = &(f->polygonlist[j - 1]);
968 stringptr = readnumberline(inputline, infile, infilename);
969 p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
970 if (p->numberofvertices < 1) {
971 printf(
"Error: Wrong polygon %d in facet %d\n", j, i);
975 p->vertexlist =
new int[p->numberofvertices];
977 for (k = 1; k <= p->numberofvertices; k++) {
978 stringptr = findnextnumber(stringptr);
979 if (*stringptr ==
'\0') {
982 stringptr = readnumberline(inputline, infile, infilename);
983 if (*stringptr ==
'\0') {
984 printf(
"Error: Missing %d endpoints of polygon %d in facet %d",
985 p->numberofvertices - k, j, i);
989 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
992 if (j <= f->numberofpolygons) {
997 delete [] f->polygonlist;
999 f->numberofpolygons = j - 1;
1001 f->numberofholes = 0;
1005 if (f->numberofholes > 0) {
1007 f->holelist =
new REAL[f->numberofholes * 3];
1010 for (j = 1; j <= f->numberofholes; j++) {
1011 stringptr = readnumberline(inputline, infile, infilename);
1012 for (k = 1; k <= 3; k++) {
1013 stringptr = findnextnumber(stringptr);
1014 if (*stringptr ==
'\0') {
1015 printf(
"Error: Hole %d in facet %d has no coordinates", j, i);
1018 f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
1025 if (j <= f->numberofholes) {
1031 if (i <= numberoffacets) {
1033 numberoffacets = i - 1;
1039 for (i = 1; i <= numberoffacets; i++) {
1040 f = &(facetlist[i - 1]);
1044 f->numberofpolygons = 1;
1045 f->polygonlist =
new polygon[f->numberofpolygons];
1046 p = &(f->polygonlist[0]);
1049 stringptr = readnumberline(inputline, infile, insmeshfilename);
1050 p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
1051 if (p->numberofvertices < 1) {
1052 printf(
"Error: Wrong number of vertex in facet %d\n", i);
1056 p->vertexlist =
new int[p->numberofvertices];
1057 for (k = 1; k <= p->numberofvertices; k++) {
1058 stringptr = findnextnumber(stringptr);
1059 if (*stringptr ==
'\0') {
1062 stringptr = readnumberline(inputline, infile, infilename);
1063 if (*stringptr ==
'\0') {
1064 printf(
"Error: Missing %d endpoints in facet %d",
1065 p->numberofvertices - k, i);
1069 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
1071 if (k <= p->numberofvertices) {
1077 stringptr = findnextnumber(stringptr);
1078 if (*stringptr ==
'\0') {
1081 currentmarker = (int) strtol(stringptr, &stringptr, 0);
1083 facetmarkerlist[i - 1] = currentmarker;
1086 if (i <= numberoffacets) {
1088 numberoffacets = i - 1;
1095 stringptr = readnumberline(inputline, infile, infilename);
1096 if (stringptr == NULL) {
1101 if (*stringptr !=
'\0') {
1102 numberofholes = (int) strtol (stringptr, &stringptr, 0);
1106 if (numberofholes > 0) {
1108 holelist =
new REAL[numberofholes * 3];
1109 for (i = 0; i < 3 * numberofholes; i += 3) {
1110 stringptr = readnumberline(inputline, infile, infilename);
1111 stringptr = findnextnumber(stringptr);
1112 if (*stringptr ==
'\0') {
1113 printf(
"Error: Hole %d has no x coord.\n", firstnumber + (i / 3));
1116 holelist[i] = (REAL) strtod(stringptr, &stringptr);
1118 stringptr = findnextnumber(stringptr);
1119 if (*stringptr ==
'\0') {
1120 printf(
"Error: Hole %d has no y coord.\n", firstnumber + (i / 3));
1123 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
1125 stringptr = findnextnumber(stringptr);
1126 if (*stringptr ==
'\0') {
1127 printf(
"Error: Hole %d has no z coord.\n", firstnumber + (i / 3));
1130 holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
1133 if (i < 3 * numberofholes) {
1142 stringptr = readnumberline(inputline, infile, NULL);
1143 if (stringptr != (
char *) NULL && *stringptr !=
'\0') {
1144 numberofregions = (int) strtol (stringptr, &stringptr, 0);
1146 numberofregions = 0;
1148 if (numberofregions > 0) {
1150 regionlist =
new REAL[numberofregions * 5];
1152 for (i = 0; i < numberofregions; i++) {
1153 stringptr = readnumberline(inputline, infile, infilename);
1154 stringptr = findnextnumber(stringptr);
1155 if (*stringptr ==
'\0') {
1156 printf(
"Error: Region %d has no x coordinate.\n", firstnumber + i);
1159 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1161 stringptr = findnextnumber(stringptr);
1162 if (*stringptr ==
'\0') {
1163 printf(
"Error: Region %d has no y coordinate.\n", firstnumber + i);
1166 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1168 stringptr = findnextnumber(stringptr);
1169 if (*stringptr ==
'\0') {
1170 printf(
"Error: Region %d has no z coordinate.\n", firstnumber + i);
1173 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1175 stringptr = findnextnumber(stringptr);
1176 if (*stringptr ==
'\0') {
1177 printf(
"Error: Region %d has no region attrib.\n", firstnumber + i);
1180 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1182 stringptr = findnextnumber(stringptr);
1183 if (*stringptr ==
'\0') {
1184 regionlist[index] = regionlist[index - 1];
1186 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
1190 if (i < numberofregions) {
1214 bool tetgenio::load_off(
const char* filebasename)
1219 char infilename[FILENAMESIZE];
1220 char buffer[INPUTLINESIZE];
1223 int nverts = 0, iverts = 0;
1224 int nfaces = 0, ifaces = 0;
1226 int line_count = 0, i;
1230 int smallestidx = 0;
1232 strncpy(infilename, filebasename, 1024 - 1);
1233 infilename[FILENAMESIZE - 1] =
'\0';
1234 if (infilename[0] ==
'\0') {
1235 printf(
"Error: No filename.\n");
1238 if (strcmp(&infilename[strlen(infilename) - 4],
".off") != 0) {
1239 strcat(infilename,
".off");
1242 if (!(fp = fopen(infilename,
"r"))) {
1243 printf(
" Unable to open file %s\n", infilename);
1246 printf(
"Opening %s.\n", infilename);
1248 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1252 bufferp = strstr(bufferp,
"OFF");
1253 if (bufferp != NULL) {
1255 bufferp = findnextnumber(bufferp);
1256 if (*bufferp ==
'\0') {
1258 bufferp = readline(buffer, fp, &line_count);
1260 if ((sscanf(bufferp,
"%d%d%d", &nverts, &nfaces, &nedges) != 3)
1262 printf(
"Syntax error reading header on line %d in file %s\n",
1263 line_count, infilename);
1269 numberofpoints = nverts;
1270 pointlist =
new REAL[nverts * 3];
1271 smallestidx = nverts + 1;
1274 numberoffacets = nfaces;
1278 }
else if (iverts < nverts) {
1280 coord = &pointlist[iverts * 3];
1281 for (i = 0; i < 3; i++) {
1282 if (*bufferp ==
'\0') {
1283 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1284 line_count, infilename);
1288 coord[i] = (REAL) strtod(bufferp, &bufferp);
1289 bufferp = findnextnumber(bufferp);
1292 }
else if (ifaces < nfaces) {
1294 f = &facetlist[ifaces];
1297 f->numberofpolygons = 1;
1299 p = &f->polygonlist[0];
1302 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1303 if (p->numberofvertices == 0) {
1304 printf(
"Syntax error reading polygon on line %d in file %s\n",
1305 line_count, infilename);
1310 p->vertexlist =
new int[p->numberofvertices];
1311 for (i = 0; i < p->numberofvertices; i++) {
1312 bufferp = findnextnumber(bufferp);
1313 if (*bufferp ==
'\0') {
1314 printf(
"Syntax error reading polygon on line %d in file %s\n",
1315 line_count, infilename);
1319 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1321 if (p->vertexlist[i] < smallestidx) {
1322 smallestidx = p->vertexlist[i];
1328 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1338 if (smallestidx == 0) {
1340 }
else if (smallestidx == 1) {
1343 printf(
"A wrong smallest index (%d) was detected in file %s\n",
1344 smallestidx, infilename);
1348 if (iverts != nverts) {
1349 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1350 nverts, iverts, infilename);
1353 if (ifaces != nfaces) {
1354 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1355 nfaces, ifaces, infilename);
1376 bool tetgenio::load_ply(
const char* filebasename)
1381 char infilename[FILENAMESIZE];
1382 char buffer[INPUTLINESIZE];
1383 char *bufferp, *str;
1385 int endheader = 0, format = 0;
1386 int nverts = 0, iverts = 0;
1387 int nfaces = 0, ifaces = 0;
1388 int line_count = 0, i;
1392 int smallestidx = 0;
1394 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1395 infilename[FILENAMESIZE - 1] =
'\0';
1396 if (infilename[0] ==
'\0') {
1397 printf(
"Error: No filename.\n");
1400 if (strcmp(&infilename[strlen(infilename) - 4],
".ply") != 0) {
1401 strcat(infilename,
".ply");
1404 if (!(fp = fopen(infilename,
"r"))) {
1405 printf(
"Error: Unable to open file %s\n", infilename);
1408 printf(
"Opening %s.\n", infilename);
1410 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1413 str = strstr(bufferp,
"end_header");
1415 if (!str) str = strstr(bufferp,
"End_header");
1416 if (!str) str = strstr(bufferp,
"End_Header");
1423 if (nverts == 0 || nfaces == 0) {
1425 str = strstr(bufferp,
"element");
1426 if (!str) str = strstr(bufferp,
"Element");
1428 bufferp = findnextfield(str);
1429 if (*bufferp ==
'\0') {
1430 printf(
"Syntax error reading element type on line%d in file %s\n",
1431 line_count, infilename);
1437 str = strstr(bufferp,
"vertex");
1438 if (!str) str = strstr(bufferp,
"Vertex");
1440 bufferp = findnextnumber(str);
1441 if (*bufferp ==
'\0') {
1442 printf(
"Syntax error reading vertex number on line");
1443 printf(
" %d in file %s\n", line_count, infilename);
1447 nverts = (int) strtol(bufferp, &bufferp, 0);
1450 numberofpoints = nverts;
1451 pointlist =
new REAL[nverts * 3];
1452 smallestidx = nverts + 1;
1458 str = strstr(bufferp,
"face");
1459 if (!str) str = strstr(bufferp,
"Face");
1461 bufferp = findnextnumber(str);
1462 if (*bufferp ==
'\0') {
1463 printf(
"Syntax error reading face number on line");
1464 printf(
" %d in file %s\n", line_count, infilename);
1468 nfaces = (int) strtol(bufferp, &bufferp, 0);
1471 numberoffacets = nfaces;
1480 str = strstr(bufferp,
"format");
1481 if (!str) str = strstr(bufferp,
"Format");
1484 bufferp = findnextfield(str);
1486 str = strstr(bufferp,
"ascii");
1487 if (!str) str = strstr(bufferp,
"ASCII");
1489 printf(
"This routine only reads ascii format of ply files.\n");
1490 printf(
"Hint: You can convert the binary to ascii format by\n");
1491 printf(
" using the provided ply tools:\n");
1492 printf(
" ply2ascii < %s > ascii_%s\n", infilename, infilename);
1498 }
else if (iverts < nverts) {
1500 coord = &pointlist[iverts * 3];
1501 for (i = 0; i < 3; i++) {
1502 if (*bufferp ==
'\0') {
1503 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1504 line_count, infilename);
1508 coord[i] = (REAL) strtod(bufferp, &bufferp);
1509 bufferp = findnextnumber(bufferp);
1512 }
else if (ifaces < nfaces) {
1514 f = &facetlist[ifaces];
1517 f->numberofpolygons = 1;
1519 p = &f->polygonlist[0];
1522 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1523 if (p->numberofvertices == 0) {
1524 printf(
"Syntax error reading polygon on line %d in file %s\n",
1525 line_count, infilename);
1530 p->vertexlist =
new int[p->numberofvertices];
1531 for (i = 0; i < p->numberofvertices; i++) {
1532 bufferp = findnextnumber(bufferp);
1533 if (*bufferp ==
'\0') {
1534 printf(
"Syntax error reading polygon on line %d in file %s\n",
1535 line_count, infilename);
1539 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1540 if (p->vertexlist[i] < smallestidx) {
1541 smallestidx = p->vertexlist[i];
1547 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1557 if (smallestidx == 0) {
1559 }
else if (smallestidx == 1) {
1562 printf(
"A wrong smallest index (%d) was detected in file %s\n",
1563 smallestidx, infilename);
1567 if (iverts != nverts) {
1568 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1569 nverts, iverts, infilename);
1572 if (ifaces != nfaces) {
1573 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1574 nfaces, ifaces, infilename);
1595 void SwapBytes(
char *array,
int size,
int n)
1597 char *x =
new char[size];
1598 for(
int i = 0; i < n; i++) {
1599 char *a = &array[i * size];
1601 for(
int c = 0; c < size; c++)
1602 a[size - 1 - c] = x[c];
1607 bool tetgenio::load_stl(
const char* filebasename)
1613 char infilename[FILENAMESIZE];
1614 char buffer[INPUTLINESIZE];
1615 char *bufferp, *str;
1618 int nverts = 0, iverts = 0;
1620 int line_count = 0, i;
1622 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1623 infilename[FILENAMESIZE - 1] =
'\0';
1624 if (infilename[0] ==
'\0') {
1625 printf(
"Error: No filename.\n");
1628 if (strcmp(&infilename[strlen(infilename) - 4],
".stl") != 0) {
1629 strcat(infilename,
".stl");
1632 if (!(fp = fopen(infilename,
"rb"))) {
1633 printf(
"Error: Unable to open file %s\n", infilename);
1636 printf(
"Opening %s.\n", infilename);
1639 if(!fgets(buffer,
sizeof(buffer), fp)){ fclose(fp);
return 0; }
1640 bool binary = strncmp(buffer,
"solid", 5) && strncmp(buffer,
"SOLID", 5);
1647 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1652 bufferp = strstr(bufferp,
"solid");
1653 if (bufferp != NULL) {
1660 bufferp = strstr(bufferp,
"endsolid");
1661 if (bufferp != NULL) {
1666 bufferp = strstr(bufferp,
"vertex");
1667 if (bufferp != NULL) {
1668 plist->newindex((
void **) &coord);
1669 for (i = 0; i < 3; i++) {
1670 bufferp = findnextnumber(bufferp);
1671 if (*bufferp ==
'\0') {
1672 printf(
"Syntax error reading vertex coords on line %d\n",
1678 coord[i] = (REAL) strtod(bufferp, &bufferp);
1690 if(!fread(header,
sizeof(
char), 80, fp))
break;
1691 unsigned int nfacets = 0;
1692 size_t ret = fread(&nfacets,
sizeof(
unsigned int), 1, fp);
1694 if(nfacets > 100000000){
1697 SwapBytes((
char*)&nfacets,
sizeof(
unsigned int), 1);
1701 char *data =
new char[nfacets * 50 *
sizeof(char)];
1702 ret = fread(data,
sizeof(
char), nfacets * 50, fp);
1703 if(ret == nfacets * 50){
1704 for(
unsigned int i = 0; i < nfacets; i++) {
1705 float *xyz = (
float *)&data[i * 50 *
sizeof(
char)];
1706 if(swap) SwapBytes((
char*)xyz,
sizeof(
float), 12);
1707 for(
int j = 0; j < 3; j++){
1711 plist->newindex((
void **) &coord);
1712 coord[0] = xyz[3 + 3 * j];
1713 coord[1] = xyz[3 + 3 * j + 1];
1714 coord[2] = xyz[3 + 3 * j + 2];
1725 nverts = (int) plist->objects;
1727 if (nverts == 0 || (nverts % 3 != 0)) {
1728 printf(
"Error: Wrong number of vertices in file %s.\n", infilename);
1732 numberofpoints = nverts;
1733 pointlist =
new REAL[nverts * 3];
1734 for (i = 0; i < nverts; i++) {
1735 coord = (
double *) fastlookup(plist, i);
1737 pointlist[iverts] = (REAL) coord[0];
1738 pointlist[iverts + 1] = (REAL) coord[1];
1739 pointlist[iverts + 2] = (REAL) coord[2];
1742 nfaces = (int) (nverts / 3);
1743 numberoffacets = nfaces;
1748 iverts = firstnumber;
1749 for (i = 0; i < nfaces; i++) {
1753 f->numberofpolygons = 1;
1755 p = &f->polygonlist[0];
1758 p->numberofvertices = 3;
1759 p->vertexlist =
new int[p->numberofvertices];
1760 p->vertexlist[0] = iverts;
1761 p->vertexlist[1] = iverts + 1;
1762 p->vertexlist[2] = iverts + 2;
1779 bool tetgenio::load_medit(
const char* filebasename,
int istetmesh)
1784 char infilename[FILENAMESIZE];
1785 char buffer[INPUTLINESIZE];
1786 char *bufferp, *str;
1798 int smallestidx = 0;
1800 strncpy(infilename, filebasename, FILENAMESIZE - 1);
1801 infilename[FILENAMESIZE - 1] =
'\0';
1802 if (infilename[0] ==
'\0') {
1803 printf(
"Error: No filename.\n");
1806 if (strcmp(&infilename[strlen(infilename) - 5],
".mesh") != 0) {
1807 strcat(infilename,
".mesh");
1810 if (!(fp = fopen(infilename,
"r"))) {
1811 printf(
"Error: Unable to open file %s\n", infilename);
1814 printf(
"Opening %s.\n", infilename);
1816 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1817 if (*bufferp ==
'#')
continue;
1818 if (dimension == 0) {
1820 str = strstr(bufferp,
"Dimension");
1821 if (!str) str = strstr(bufferp,
"dimension");
1822 if (!str) str = strstr(bufferp,
"DIMENSION");
1825 bufferp = findnextnumber(str);
1826 if (*bufferp ==
'\0') {
1828 bufferp = readline(buffer, fp, &line_count);
1830 dimension = (int) strtol(bufferp, &bufferp, 0);
1831 if (dimension != 2 && dimension != 3) {
1832 printf(
"Unknown dimension in file on line %d in file %s\n",
1833 line_count, infilename);
1837 mesh_dim = dimension;
1842 str = strstr(bufferp,
"Vertices");
1843 if (!str) str = strstr(bufferp,
"vertices");
1844 if (!str) str = strstr(bufferp,
"VERTICES");
1847 bufferp = findnextnumber(str);
1848 if (*bufferp ==
'\0') {
1850 bufferp = readline(buffer, fp, &line_count);
1852 nverts = (int) strtol(bufferp, &bufferp, 0);
1854 smallestidx = nverts + 1;
1857 numberofpoints = nverts;
1858 pointlist =
new REAL[nverts * 3];
1861 for (i = 0; i < nverts; i++) {
1862 bufferp = readline(buffer, fp, &line_count);
1863 if (bufferp == NULL) {
1864 printf(
"Unexpected end of file on line %d in file %s\n",
1865 line_count, infilename);
1870 coord = &pointlist[i * 3];
1871 for (j = 0; j < 3; j++) {
1872 if (*bufferp ==
'\0') {
1873 printf(
"Syntax error reading vertex coords on line");
1874 printf(
" %d in file %s\n", line_count, infilename);
1878 if ((j < 2) || (dimension == 3)) {
1879 coord[j] = (REAL) strtod(bufferp, &bufferp);
1883 bufferp = findnextnumber(bufferp);
1892 str = strstr(bufferp,
"Tetrahedra");
1893 if (!str) str = strstr(bufferp,
"tetrahedra");
1894 if (!str) str = strstr(bufferp,
"TETRAHEDRA");
1900 bufferp = findnextnumber(str);
1901 if (*bufferp ==
'\0') {
1903 bufferp = readline(buffer, fp, &line_count);
1905 ntets = strtol(bufferp, &bufferp, 0);
1908 numberoftetrahedra = ntets;
1909 numberofcorners = 4;
1910 numberoftetrahedronattributes = 1;
1911 tetrahedronlist =
new int[ntets * 4];
1912 tetrahedronattributelist =
new REAL[ntets];
1916 for (i = 0; i < numberoftetrahedra; i++) {
1917 plist = &(tetrahedronlist[i * 4]);
1918 bufferp = readline(buffer, fp, &line_count);
1919 if (bufferp == NULL) {
1920 printf(
"Unexpected end of file on line %d in file %s\n",
1921 line_count, infilename);
1926 for (j = 0; j < corners; j++) {
1927 if (*bufferp ==
'\0') {
1928 printf(
"Syntax error reading face on line %d in file %s\n",
1929 line_count, infilename);
1933 plist[j] = (int) strtol(bufferp, &bufferp, 0);
1935 if (plist[j] < smallestidx) smallestidx = plist[j];
1936 bufferp = findnextnumber(bufferp);
1939 tetrahedronattributelist[i] = 0;
1940 if (*bufferp !=
'\0') {
1941 tetrahedronattributelist[i] = (REAL) strtol(bufferp, &bufferp, 0);
1948 str = strstr(bufferp,
"Triangles");
1949 if (!str) str = strstr(bufferp,
"triangles");
1950 if (!str) str = strstr(bufferp,
"TRIANGLES");
1954 str = strstr(bufferp,
"Quadrilaterals");
1955 if (!str) str = strstr(bufferp,
"quadrilaterals");
1956 if (!str) str = strstr(bufferp,
"QUADRILATERALS");
1961 if (corners == 3 || corners == 4) {
1963 bufferp = findnextnumber(str);
1964 if (*bufferp ==
'\0') {
1966 bufferp = readline(buffer, fp, &line_count);
1968 nfaces = strtol(bufferp, &bufferp, 0);
1973 if (numberoffacets > 0) {
1977 tmpfmlist =
new int[numberoffacets + nfaces];
1979 for (i = 0; i < numberoffacets; i++) {
1983 tmpfmlist[i] = facetmarkerlist[i];
1986 delete [] facetlist;
1987 delete [] facetmarkerlist;
1989 facetlist = tmpflist;
1990 facetmarkerlist = tmpfmlist;
1994 facetmarkerlist =
new int[nfaces];
1999 numberoftrifaces = nfaces;
2000 trifacelist =
new int[nfaces * 3];
2001 trifacemarkerlist =
new int[nfaces];
2007 for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
2008 bufferp = readline(buffer, fp, &line_count);
2009 if (bufferp == NULL) {
2010 printf(
"Unexpected end of file on line %d in file %s\n",
2011 line_count, infilename);
2018 f->numberofpolygons = 1;
2020 p = &f->polygonlist[0];
2022 p->numberofvertices = corners;
2024 p->vertexlist =
new int[p->numberofvertices];
2026 for (j = 0; j < corners; j++) {
2027 if (*bufferp ==
'\0') {
2028 printf(
"Syntax error reading face on line %d in file %s\n",
2029 line_count, infilename);
2033 p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
2035 if (p->vertexlist[j] < smallestidx) {
2036 smallestidx = p->vertexlist[j];
2038 bufferp = findnextnumber(bufferp);
2041 facetmarkerlist[i] = 0;
2042 if (*bufferp !=
'\0') {
2043 facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
2047 numberoffacets += nfaces;
2052 for (i = 0; i < numberoftrifaces; i++) {
2053 plist = &(trifacelist[i * 3]);
2054 bufferp = readline(buffer, fp, &line_count);
2055 if (bufferp == NULL) {
2056 printf(
"Unexpected end of file on line %d in file %s\n",
2057 line_count, infilename);
2062 for (j = 0; j < corners; j++) {
2063 if (*bufferp ==
'\0') {
2064 printf(
"Syntax error reading face on line %d in file %s\n",
2065 line_count, infilename);
2069 plist[j] = (int) strtol(bufferp, &bufferp, 0);
2071 if (plist[j] < smallestidx) {
2072 smallestidx = plist[j];
2074 bufferp = findnextnumber(bufferp);
2077 trifacemarkerlist[i] = 0;
2078 if (*bufferp !=
'\0') {
2079 trifacemarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
2092 if (smallestidx == 0) {
2094 }
else if (smallestidx == 1) {
2097 printf(
"A wrong smallest index (%d) was detected in file %s\n",
2098 smallestidx, infilename);
2116 void swapBytes(
unsigned char* var,
int size)
2123 c = var[i]; var[i] = var[j]; var[j] = c;
2128 bool testIsBigEndian()
2130 short word = 0x4321;
2131 if((*(
char *)& word) != 0x21)
2137 bool tetgenio::load_vtk(
const char* filebasename)
2142 char infilename[FILENAMESIZE];
2143 char line[INPUTLINESIZE];
2144 char mode[128],
id[256], fmt[64];
2156 bool ImALittleEndian = !testIsBigEndian();
2158 int smallestidx = 0;
2160 strncpy(infilename, filebasename, FILENAMESIZE - 1);
2161 infilename[FILENAMESIZE - 1] =
'\0';
2162 if (infilename[0] ==
'\0') {
2163 printf(
"Error: No filename.\n");
2166 if (strcmp(&infilename[strlen(infilename) - 4],
".vtk") != 0) {
2167 strcat(infilename,
".vtk");
2169 if (!(fp = fopen(infilename,
"r"))) {
2170 printf(
"Error: Unable to open file %s\n", infilename);
2173 printf(
"Opening %s.\n", infilename);
2177 strcpy(mode,
"BINARY");
2179 while((bufferp = readline(line, fp, &line_count)) != NULL) {
2180 if(strlen(line) == 0)
continue;
2182 if(line[0] ==
'#' || line[0]==
'\n' || line[0] == 10 || line[0] == 13 ||
2183 line[0] == 32)
continue;
2185 sscanf(line,
"%s",
id);
2186 if(!strcmp(
id,
"ASCII")) {
2187 strcpy(mode,
"ASCII");
2190 if(!strcmp(
id,
"POINTS")) {
2191 sscanf(line,
"%s %d %s",
id, &nverts, fmt);
2193 numberofpoints = nverts;
2194 pointlist =
new REAL[nverts * 3];
2195 smallestidx = nverts + 1;
2198 if(!strcmp(mode,
"BINARY")) {
2199 for(i = 0; i < nverts; i++) {
2200 coord = &pointlist[i * 3];
2201 if(!strcmp(fmt,
"double")) {
2202 fread((
char*)(&(coord[0])),
sizeof(
double), 1, fp);
2203 fread((
char*)(&(coord[1])),
sizeof(
double), 1, fp);
2204 fread((
char*)(&(coord[2])),
sizeof(
double), 1, fp);
2205 if(ImALittleEndian){
2206 swapBytes((
unsigned char *) &(coord[0]),
sizeof(coord[0]));
2207 swapBytes((
unsigned char *) &(coord[1]),
sizeof(coord[1]));
2208 swapBytes((
unsigned char *) &(coord[2]),
sizeof(coord[2]));
2210 }
else if(!strcmp(fmt,
"float")) {
2211 fread((
char*)(&_x),
sizeof(
float), 1, fp);
2212 fread((
char*)(&_y),
sizeof(
float), 1, fp);
2213 fread((
char*)(&_z),
sizeof(
float), 1, fp);
2214 if(ImALittleEndian){
2215 swapBytes((
unsigned char *) &_x,
sizeof(_x));
2216 swapBytes((
unsigned char *) &_y,
sizeof(_y));
2217 swapBytes((
unsigned char *) &_z,
sizeof(_z));
2219 coord[0] = double(_x);
2220 coord[1] = double(_y);
2221 coord[2] = double(_z);
2223 printf(
"Error: Only float or double formats are supported!\n");
2227 }
else if(!strcmp(mode,
"ASCII")) {
2228 for(i = 0; i < nverts; i++){
2229 bufferp = readline(line, fp, &line_count);
2230 if (bufferp == NULL) {
2231 printf(
"Unexpected end of file on line %d in file %s\n",
2232 line_count, infilename);
2237 coord = &pointlist[i * 3];
2238 for (j = 0; j < 3; j++) {
2239 if (*bufferp ==
'\0') {
2240 printf(
"Syntax error reading vertex coords on line");
2241 printf(
" %d in file %s\n", line_count, infilename);
2245 coord[j] = (REAL) strtod(bufferp, &bufferp);
2246 bufferp = findnextnumber(bufferp);
2253 if(!strcmp(
id,
"POLYGONS")) {
2254 sscanf(line,
"%s %d %d",
id, &nfaces, &dummy);
2256 numberoffacets = nfaces;
2260 if(!strcmp(mode,
"BINARY")) {
2261 for(i = 0; i < nfaces; i++){
2262 fread((
char*)(&nn),
sizeof(
int), 1, fp);
2263 if(ImALittleEndian){
2264 swapBytes((
unsigned char *) &nn,
sizeof(nn));
2269 printf(
"Error: No mixed cells are allowed.\n");
2274 fread((
char*)(&id1),
sizeof(
int), 1, fp);
2275 fread((
char*)(&id2),
sizeof(
int), 1, fp);
2276 fread((
char*)(&id3),
sizeof(
int), 1, fp);
2277 if(ImALittleEndian){
2278 swapBytes((
unsigned char *) &id1,
sizeof(id1));
2279 swapBytes((
unsigned char *) &id2,
sizeof(id2));
2280 swapBytes((
unsigned char *) &id3,
sizeof(id3));
2285 f->numberofpolygons = 1;
2287 p = &f->polygonlist[0];
2290 p->numberofvertices = 3;
2292 p->vertexlist =
new int[p->numberofvertices];
2293 p->vertexlist[0] = id1;
2294 p->vertexlist[1] = id2;
2295 p->vertexlist[2] = id3;
2297 for (j = 0; j < 3; j++) {
2298 if (p->vertexlist[j] < smallestidx) {
2299 smallestidx = p->vertexlist[j];
2303 printf(
"Error: Only triangles are supported\n");
2307 }
else if(!strcmp(mode,
"ASCII")) {
2308 for(i = 0; i < nfaces; i++) {
2309 bufferp = readline(line, fp, &line_count);
2310 nn = (int) strtol(bufferp, &bufferp, 0);
2314 printf(
"Error: No mixed cells are allowed.\n");
2319 bufferp = findnextnumber(bufferp);
2320 id1 = (int) strtol(bufferp, &bufferp, 0);
2321 bufferp = findnextnumber(bufferp);
2322 id2 = (int) strtol(bufferp, &bufferp, 0);
2323 bufferp = findnextnumber(bufferp);
2324 id3 = (int) strtol(bufferp, &bufferp, 0);
2328 f->numberofpolygons = 1;
2330 p = &f->polygonlist[0];
2333 p->numberofvertices = 3;
2335 p->vertexlist =
new int[p->numberofvertices];
2336 p->vertexlist[0] = id1;
2337 p->vertexlist[1] = id2;
2338 p->vertexlist[2] = id3;
2340 for (j = 0; j < 3; j++) {
2341 if (p->vertexlist[j] < smallestidx) {
2342 smallestidx = p->vertexlist[j];
2346 printf(
"Error: Only triangles are supported.\n");
2355 if (smallestidx == 0) {
2357 }
else if (smallestidx == 1) {
2360 printf(
"A wrong smallest index (%d) was detected in file %s\n",
2361 smallestidx, infilename);
2368 if(!strcmp(
id,
"LINES") || !strcmp(
id,
"CELLS")){
2369 printf(
"Warning: load_vtk(): cannot read formats LINES, CELLS.\n");
2382 bool tetgenio::load_plc(
const char* filebasename,
int object)
2386 if (
object == (
int) tetgenbehavior::NODES) {
2387 success = load_node(filebasename);
2388 }
else if (
object == (
int) tetgenbehavior::POLY) {
2389 success = load_poly(filebasename);
2390 }
else if (
object == (
int) tetgenbehavior::OFF) {
2391 success = load_off(filebasename);
2392 }
else if (
object == (
int) tetgenbehavior::PLY) {
2393 success = load_ply(filebasename);
2394 }
else if (
object == (
int) tetgenbehavior::STL) {
2395 success = load_stl(filebasename);
2396 }
else if (
object == (
int) tetgenbehavior::MEDIT) {
2397 success = load_medit(filebasename, 0);
2398 }
else if (
object == (
int) tetgenbehavior::VTK) {
2399 success = load_vtk(filebasename);
2401 success = load_poly(filebasename);
2406 load_edge(filebasename);
2407 load_var(filebasename);
2408 load_mtr(filebasename);
2420 bool tetgenio::load_tetmesh(
const char* filebasename,
int object)
2424 if (
object == (
int) tetgenbehavior::MEDIT) {
2425 success = load_medit(filebasename, 1);
2426 }
else if (
object == (
int) tetgenbehavior::NEU_MESH) {
2430 success = load_node(filebasename);
2432 success = load_tet(filebasename);
2436 load_face(filebasename);
2437 load_edge(filebasename);
2438 load_vol(filebasename);
2444 load_var(filebasename);
2445 load_mtr(filebasename);
2457 void tetgenio::save_nodes(
const char* filebasename)
2460 char outnodefilename[FILENAMESIZE];
2461 char outmtrfilename[FILENAMESIZE];
2464 sprintf(outnodefilename,
"%s.node", filebasename);
2465 std::cout <<
"Saving nodes to " << outnodefilename << std::endl;
2466 fout = fopen(outnodefilename,
"w");
2467 fprintf(fout,
"%d %d %d %d\n", numberofpoints, mesh_dim,
2468 numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
2469 for (i = 0; i < numberofpoints; i++) {
2470 if (mesh_dim == 2) {
2471 fprintf(fout,
"%d %.16g %.16g", i + firstnumber, pointlist[i * 3],
2472 pointlist[i * 3 + 1]);
2474 fprintf(fout,
"%d %.16g %.16g %.16g", i + firstnumber,
2475 pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
2477 for (j = 0; j < numberofpointattributes; j++) {
2478 fprintf(fout,
" %.16g",
2479 pointattributelist[i * numberofpointattributes + j]);
2481 if (pointmarkerlist != NULL) {
2482 fprintf(fout,
" %d", pointmarkerlist[i]);
2484 fprintf(fout,
"\n");
2489 if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
2490 sprintf(outmtrfilename,
"%s.mtr", filebasename);
2491 std::cout <<
"Saving metrics to " << outmtrfilename << std::endl;
2492 fout = fopen(outmtrfilename,
"w");
2493 fprintf(fout,
"%d %d\n", numberofpoints, numberofpointmtrs);
2494 for (i = 0; i < numberofpoints; i++) {
2495 for (j = 0; j < numberofpointmtrs; j++) {
2496 fprintf(fout,
"%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
2498 fprintf(fout,
"\n");
2510 void tetgenio::save_elements(
const char* filebasename)
2513 char outelefilename[FILENAMESIZE];
2516 sprintf(outelefilename,
"%s.ele", filebasename);
2517 std::cout <<
"Saving elements to " << outelefilename << std::endl;
2518 fout = fopen(outelefilename,
"w");
2519 if (mesh_dim == 3) {
2520 fprintf(fout,
"%d %d %d\n", numberoftetrahedra, numberofcorners,
2521 numberoftetrahedronattributes);
2522 for (i = 0; i < numberoftetrahedra; i++) {
2523 fprintf(fout,
"%d", i + firstnumber);
2524 for (j = 0; j < numberofcorners; j++) {
2525 fprintf(fout,
" %5d", tetrahedronlist[i * numberofcorners + j]);
2527 for (j = 0; j < numberoftetrahedronattributes; j++) {
2528 fprintf(fout,
" %g",
2529 tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
2531 fprintf(fout,
"\n");
2535 fprintf(fout,
"%d %d %d\n",numberoftrifaces,3,trifacemarkerlist ? 1 : 0);
2536 for (i = 0; i < numberoftrifaces; i++) {
2537 fprintf(fout,
"%d", i + firstnumber);
2538 for (j = 0; j < 3; j++) {
2539 fprintf(fout,
" %5d", trifacelist[i * 3 + j]);
2541 if (trifacemarkerlist != NULL) {
2542 fprintf(fout,
" %d", trifacemarkerlist[i]);
2544 fprintf(fout,
"\n");
2557 void tetgenio::save_faces(
const char* filebasename)
2560 char outfacefilename[FILENAMESIZE];
2563 sprintf(outfacefilename,
"%s.face", filebasename);
2564 std::cout <<
"Saving faces to " << outfacefilename << std::endl;
2565 fout = fopen(outfacefilename,
"w");
2566 fprintf(fout,
"%d %d\n", numberoftrifaces,
2567 trifacemarkerlist != NULL ? 1 : 0);
2568 for (i = 0; i < numberoftrifaces; i++) {
2569 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3],
2570 trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
2571 if (trifacemarkerlist != NULL) {
2572 fprintf(fout,
" %d", trifacemarkerlist[i]);
2574 fprintf(fout,
"\n");
2586 void tetgenio::save_edges(
const char* filebasename)
2589 char outedgefilename[FILENAMESIZE];
2592 sprintf(outedgefilename,
"%s.edge", filebasename);
2593 std::cout <<
"Saving edges to " << outedgefilename << std::endl;
2594 fout = fopen(outedgefilename,
"w");
2595 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2596 for (i = 0; i < numberofedges; i++) {
2597 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2598 edgelist[i * 2 + 1]);
2599 if (edgemarkerlist != NULL) {
2600 fprintf(fout,
" %d", edgemarkerlist[i]);
2602 fprintf(fout,
"\n");
2614 void tetgenio::save_neighbors(
const char* filebasename)
2617 char outneighborfilename[FILENAMESIZE];
2620 sprintf(outneighborfilename,
"%s.neigh", filebasename);
2621 std::cout <<
"Saving neighbors to " << outneighborfilename << std::endl;
2622 fout = fopen(outneighborfilename,
"w");
2623 fprintf(fout,
"%d %d\n", numberoftetrahedra, mesh_dim + 1);
2624 for (i = 0; i < numberoftetrahedra; i++) {
2625 if (mesh_dim == 2) {
2626 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3],
2627 neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
2629 fprintf(fout,
"%d %5d %5d %5d %5d", i + firstnumber,
2630 neighborlist[i * 4], neighborlist[i * 4 + 1],
2631 neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
2633 fprintf(fout,
"\n");
2647 void tetgenio::save_poly(
const char* filebasename)
2652 char outpolyfilename[FILENAMESIZE];
2655 sprintf(outpolyfilename,
"%s.poly", filebasename);
2656 std::cout <<
"Saving poly to " << outpolyfilename << std::endl;
2657 fout = fopen(outpolyfilename,
"w");
2662 fprintf(fout,
"%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
2663 pointmarkerlist != NULL ? 1 : 0);
2666 if (mesh_dim == 2) {
2668 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2669 for (i = 0; i < numberofedges; i++) {
2670 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2671 edgelist[i * 2 + 1]);
2672 if (edgemarkerlist != NULL) {
2673 fprintf(fout,
" %d", edgemarkerlist[i]);
2675 fprintf(fout,
"\n");
2679 fprintf(fout,
"%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
2680 for (i = 0; i < numberoffacets; i++) {
2681 f = &(facetlist[i]);
2682 fprintf(fout,
"%d %d %d # %d\n", f->numberofpolygons,f->numberofholes,
2683 facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
2685 for (j = 0; j < f->numberofpolygons; j++) {
2686 p = &(f->polygonlist[j]);
2687 fprintf(fout,
"%d ", p->numberofvertices);
2688 for (k = 0; k < p->numberofvertices; k++) {
2689 if (((k + 1) % 10) == 0) {
2690 fprintf(fout,
"\n ");
2692 fprintf(fout,
" %d", p->vertexlist[k]);
2694 fprintf(fout,
"\n");
2697 for (j = 0; j < f->numberofholes; j++) {
2698 fprintf(fout,
"%d %.12g %.12g %.12g\n", j + firstnumber,
2699 f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
2705 fprintf(fout,
"%d\n", numberofholes);
2706 for (i = 0; i < numberofholes; i++) {
2708 fprintf(fout,
"%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim],
2709 holelist[i * mesh_dim + 1]);
2710 if (mesh_dim == 3) {
2712 fprintf(fout,
" %.12g", holelist[i * mesh_dim + 2]);
2714 fprintf(fout,
"\n");
2718 fprintf(fout,
"%d\n", numberofregions);
2719 for (i = 0; i < numberofregions; i++) {
2720 if (mesh_dim == 2) {
2723 fprintf(fout,
"%d %.12g %.12g %.12g %.12g\n", i + firstnumber,
2724 regionlist[i * 4], regionlist[i * 4 + 1],
2725 regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
2729 fprintf(fout,
"%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber,
2730 regionlist[i * 5], regionlist[i * 5 + 1],
2731 regionlist[i * 5 + 2], regionlist[i * 5 + 3],
2732 regionlist[i * 5 + 4]);
2747 void tetgenio::save_faces2smesh(
char* filebasename)
2750 char outsmeshfilename[FILENAMESIZE];
2753 sprintf(outsmeshfilename,
"%s.smesh", filebasename);
2754 std::cout <<
"Saving faces to " << outsmeshfilename << std::endl;
2755 fout = fopen(outsmeshfilename,
"w");
2760 fprintf(fout,
"%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
2761 pointmarkerlist != NULL ? 1 : 0);
2764 fprintf(fout,
"%d %d\n", numberoftrifaces,
2765 trifacemarkerlist != NULL ? 1 : 0);
2768 for (i = 0; i < numberoftrifaces; i++) {
2770 fprintf(fout,
"3 %d %d %d", trifacelist[j], trifacelist[j + 1],
2771 trifacelist[j + 2]);
2772 if (trifacemarkerlist != NULL) {
2773 fprintf(fout,
" %d", trifacemarkerlist[i]);
2775 fprintf(fout,
"\n");
2779 fprintf(fout,
"0\n");
2780 fprintf(fout,
"0\n");
2797 char* tetgenio::readline(
char *
string, FILE *infile,
int *linenumber)
2803 result = fgets(
string, INPUTLINESIZE - 1, infile);
2804 if (linenumber) (*linenumber)++;
2805 if (result == (
char *) NULL) {
2806 return (
char *) NULL;
2809 while ((*result ==
' ') || (*result ==
'\t')) result++;
2811 }
while ((*result ==
'\0') || (*result ==
'\r') || (*result ==
'\n'));
2824 char* tetgenio::findnextfield(
char *
string)
2830 while ((*result !=
'\0') && (*result !=
' ') && (*result !=
'\t') &&
2831 (*result !=
',') && (*result !=
';')) {
2836 while ((*result ==
' ') || (*result ==
'\t') || (*result ==
',') ||
2852 #pragma GCC diagnostic push 2853 #pragma GCC diagnostic ignored "-Wunused-parameter" 2854 char* tetgenio::readnumberline(
char *
string, FILE *infile,
char *infilename)
2860 result = fgets(
string, INPUTLINESIZE, infile);
2861 if (result == (
char *) NULL) {
2866 while ((*result !=
'\0') && (*result !=
'#')
2867 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2868 && ((*result <
'0') || (*result >
'9'))) {
2872 }
while ((*result ==
'#') || (*result ==
'\0'));
2875 #pragma GCC diagnostic pop 2886 char* tetgenio::findnextnumber(
char *
string)
2892 while ((*result !=
'\0') && (*result !=
'#') && (*result !=
' ') &&
2893 (*result !=
'\t') && (*result !=
',')) {
2898 while ((*result !=
'\0') && (*result !=
'#')
2899 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2900 && ((*result <
'0') || (*result >
'9'))) {
2904 if (*result ==
'#') {
2925 void tetgenbehavior::syntax()
2927 printf(
" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgkJBNEFICQVh] input_file\n");
2928 printf(
" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
2929 printf(
" -Y Preserves the input surface mesh (does not modify it).\n");
2930 printf(
" -r Reconstructs a previously generated mesh.\n");
2931 printf(
" -q Refines mesh (to improve mesh quality).\n");
2932 printf(
" -R Mesh coarsening (to reduce the mesh elements).\n");
2933 printf(
" -A Assigns attributes to tetrahedra in different regions.\n");
2934 printf(
" -a Applies a maximum tetrahedron volume constraint.\n");
2935 printf(
" -m Applies a mesh sizing function.\n");
2936 printf(
" -i Inserts a list of additional points.\n");
2937 printf(
" -O Specifies the level of mesh optimization.\n");
2938 printf(
" -S Specifies maximum number of added points.\n");
2939 printf(
" -T Sets a tolerance for coplanar test (default 1e-8).\n");
2940 printf(
" -X Suppresses use of exact arithmetic.\n");
2941 printf(
" -M No merge of coplanar facets or very close vertices.\n");
2942 printf(
" -w Generates weighted Delaunay (regular) triangulation.\n");
2943 printf(
" -c Retains the convex hull of the PLC.\n");
2944 printf(
" -d Detects self-intersections of facets of the PLC.\n");
2945 printf(
" -z Numbers all output items starting from zero.\n");
2946 printf(
" -f Outputs all faces to .face file.\n");
2947 printf(
" -e Outputs all edges to .edge file.\n");
2948 printf(
" -n Outputs tetrahedra neighbors to .neigh file.\n");
2949 printf(
" -v Outputs Voronoi diagram to files.\n");
2950 printf(
" -g Outputs mesh to .mesh file for viewing by Medit.\n");
2951 printf(
" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
2952 printf(
" -J No jettison of unused vertices from output .node file.\n");
2953 printf(
" -B Suppresses output of boundary information.\n");
2954 printf(
" -N Suppresses output of .node file.\n");
2955 printf(
" -E Suppresses output of .ele file.\n");
2956 printf(
" -F Suppresses output of .face and .edge file.\n");
2957 printf(
" -I Suppresses mesh iteration numbers.\n");
2958 printf(
" -C Checks the consistency of the final mesh.\n");
2959 printf(
" -Q Quiet: No terminal output except errors.\n");
2960 printf(
" -V Verbose: Detailed information, more terminal output.\n");
2961 printf(
" -h Help: A brief instruction for using TetGen.\n");
2970 void tetgenbehavior::usage()
2973 printf(
"A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
2974 printf(
"Triangulator\n");
2975 printf(
"Version 1.5\n");
2976 printf(
"August 18, 2018\n");
2978 printf(
"Copyright (C) 2002 - 2018\n");
2980 printf(
"What Can TetGen Do?\n");
2982 printf(
" TetGen generates Delaunay tetrahedralizations, constrained\n");
2983 printf(
" Delaunay tetrahedralizations, and quality tetrahedral meshes.\n");
2985 printf(
"Command Line Syntax:\n");
2987 printf(
" Below is the basic command line syntax of TetGen with a list of ");
2989 printf(
" descriptions. Underscores indicate that numbers may optionally\n");
2990 printf(
" follow certain switches. Do not leave any space between a ");
2992 printf(
" and its numeric parameter. \'input_file\' contains input data\n");
2993 printf(
" depending on the switches you supplied which may be a ");
2994 printf(
" piecewise\n");
2995 printf(
" linear complex or a list of nodes. File formats and detailed\n");
2996 printf(
" description of command line switches are found in user's ");
2997 printf(
"manual.\n");
3001 printf(
"Examples of How to Use TetGen:\n");
3003 printf(
" \'tetgen object\' reads vertices from object.node, and writes ");
3004 printf(
"their\n Delaunay tetrahedralization to object.1.node, ");
3005 printf(
"object.1.ele\n (tetrahedra), and object.1.face");
3006 printf(
" (convex hull faces).\n");
3008 printf(
" \'tetgen -p object\' reads a PLC from object.poly or object.");
3009 printf(
"smesh (and\n possibly object.node) and writes its constrained ");
3010 printf(
"Delaunay\n tetrahedralization to object.1.node, object.1.ele, ");
3011 printf(
"object.1.face,\n");
3012 printf(
" (boundary faces) and object.1.edge (boundary edges).\n");
3014 printf(
" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
3015 printf(
" object.smesh (and possibly object.node), generates a mesh ");
3016 printf(
"whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
3017 printf(
"have volume\n of 0.1 or less, and writes the mesh to ");
3018 printf(
"object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
3020 printf(
"Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
3021 terminatetetgen(NULL, 0);
3035 bool tetgenbehavior::parse_commandline(
int argc,
const char **argv)
3041 char workstring[1024];
3047 commandline[0] =
'\0';
3050 strcpy(commandline, argv[0]);
3051 strcat(commandline,
" ");
3054 for (i = startindex; i < argc; i++) {
3056 strcat(commandline, argv[i]);
3057 strcat(commandline,
" ");
3058 if (startindex == 1) {
3060 if (argv[i][0] !=
'-') {
3061 strncpy(infilename, argv[i], 1024 - 1);
3062 infilename[1024 - 1] =
'\0';
3067 for (j = startindex; argv[i][j] !=
'\0'; j++) {
3068 if (argv[i][j] ==
'p') {
3070 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3071 (argv[i][j + 1] ==
'.')) {
3073 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3074 (argv[i][j + 1] ==
'.')) {
3076 workstring[k] = argv[i][j];
3079 workstring[k] =
'\0';
3080 facet_separate_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3082 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3084 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3085 (argv[i][j + 1] ==
'.')) {
3087 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3088 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3089 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3091 workstring[k] = argv[i][j];
3094 workstring[k] =
'\0';
3095 facet_overlap_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3098 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3100 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3101 (argv[i][j + 1] ==
'.')) {
3103 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3104 (argv[i][j + 1] ==
'.')) {
3106 workstring[k] = argv[i][j];
3109 workstring[k] =
'\0';
3110 facet_small_ang_tol = (REAL) strtod(workstring, (
char **) NULL);
3113 }
else if (argv[i][j] ==
's') {
3115 }
else if (argv[i][j] ==
'Y') {
3117 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3118 nobisect_nomerge = (argv[i][j + 1] -
'0');
3121 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3123 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3124 supsteiner_level = (argv[i][j + 1] -
'0');
3128 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3130 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3131 addsteiner_algo = (argv[i][j + 1] -
'0');
3135 }
else if (argv[i][j] ==
'r') {
3137 }
else if (argv[i][j] ==
'q') {
3139 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3140 (argv[i][j + 1] ==
'.')) {
3142 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3143 (argv[i][j + 1] ==
'.')) {
3145 workstring[k] = argv[i][j];
3148 workstring[k] =
'\0';
3149 minratio = (REAL) strtod(workstring, (
char **) NULL);
3151 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3153 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3154 (argv[i][j + 1] ==
'.')) {
3156 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3157 (argv[i][j + 1] ==
'.')) {
3159 workstring[k] = argv[i][j];
3162 workstring[k] =
'\0';
3163 mindihedral = (REAL) strtod(workstring, (
char **) NULL);
3166 }
else if (argv[i][j] ==
'R') {
3168 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3169 coarsen_param = (argv[i][j + 1] -
'0');
3172 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3174 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3175 (argv[i][j + 1] ==
'.')) {
3177 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3178 (argv[i][j + 1] ==
'.')) {
3180 workstring[k] = argv[i][j];
3183 workstring[k] =
'\0';
3184 coarsen_percent = (REAL) strtod(workstring, (
char **) NULL);
3187 }
else if (argv[i][j] ==
'w') {
3189 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3190 weighted_param = (argv[i][j + 1] -
'0');
3193 }
else if (argv[i][j] ==
'b') {
3196 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3197 (argv[i][j + 1] ==
'.')) {
3199 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3200 (argv[i][j + 1] ==
'.')) {
3202 workstring[k] = argv[i][j];
3205 workstring[k] =
'\0';
3206 #pragma GCC diagnostic push 3207 #pragma GCC diagnostic ignored "-Wrestrict" 3208 brio_threshold = (int) strtol(workstring, (
char **) &workstring, 0);
3209 #pragma GCC diagnostic pop 3211 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3213 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3214 (argv[i][j + 1] ==
'.')) {
3216 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3217 (argv[i][j + 1] ==
'.')) {
3219 workstring[k] = argv[i][j];
3222 workstring[k] =
'\0';
3223 brio_ratio = (REAL) strtod(workstring, (
char **) NULL);
3226 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3228 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3229 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3231 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3232 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3234 workstring[k] = argv[i][j];
3237 workstring[k] =
'\0';
3238 #pragma GCC diagnostic push 3239 #pragma GCC diagnostic ignored "-Wrestrict" 3240 hilbert_limit = (int) strtol(workstring, (
char **) &workstring, 0);
3241 #pragma GCC diagnostic pop 3244 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3246 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3247 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3249 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3250 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'-')) {
3252 workstring[k] = argv[i][j];
3255 workstring[k] =
'\0';
3256 hilbert_order = (REAL) strtod(workstring, (
char **) NULL);
3259 if (brio_threshold == 0) {
3262 if (brio_ratio >= 1.0) {
3266 }
else if (argv[i][j] ==
'l') {
3268 }
else if (argv[i][j] ==
'L') {
3270 }
else if (argv[i][j] ==
'm') {
3272 }
else if (argv[i][j] ==
'a') {
3273 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3274 (argv[i][j + 1] ==
'.')) {
3277 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3278 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3279 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3281 workstring[k] = argv[i][j];
3284 workstring[k] =
'\0';
3285 maxvolume = (REAL) strtod(workstring, (
char **) NULL);
3289 }
else if (argv[i][j] ==
'A') {
3291 }
else if (argv[i][j] ==
'D') {
3293 if (argv[i][j + 1] ==
'l') {
3294 use_equatorial_lens = 1;
3295 }
else if ((argv[i][j + 1] >=
'1') && (argv[i][j + 1] <=
'3')) {
3296 reflevel = (argv[i][j + 1] -
'1') + 1;
3299 }
else if (argv[i][j] ==
'i') {
3300 insertaddpoints = 1;
3301 }
else if (argv[i][j] ==
'd') {
3303 }
else if (argv[i][j] ==
'c') {
3305 }
else if (argv[i][j] ==
'M') {
3308 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'1')) {
3309 nomergefacet = (argv[i][j + 1] -
'0');
3312 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3314 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'1')) {
3315 nomergevertex = (argv[i][j + 1] -
'0');
3319 }
else if (argv[i][j] ==
'X') {
3320 if (argv[i][j + 1] ==
'1') {
3326 }
else if (argv[i][j] ==
'z') {
3327 if (argv[i][j + 1] ==
'1') {
3333 }
else if (argv[i][j] ==
'f') {
3335 }
else if (argv[i][j] ==
'e') {
3337 }
else if (argv[i][j] ==
'n') {
3339 }
else if (argv[i][j] ==
'v') {
3341 }
else if (argv[i][j] ==
'g') {
3343 }
else if (argv[i][j] ==
'k') {
3345 }
else if (argv[i][j] ==
'J') {
3347 }
else if (argv[i][j] ==
'B') {
3349 }
else if (argv[i][j] ==
'N') {
3351 }
else if (argv[i][j] ==
'E') {
3353 }
else if (argv[i][j] ==
'F') {
3355 }
else if (argv[i][j] ==
'I') {
3357 }
else if (argv[i][j] ==
'S') {
3358 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3359 (argv[i][j + 1] ==
'.')) {
3361 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3362 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3363 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3365 workstring[k] = argv[i][j];
3368 workstring[k] =
'\0';
3369 steinerleft = (int) strtol(workstring, (
char **) NULL, 0);
3371 }
else if (argv[i][j] ==
'o') {
3372 if (argv[i][j + 1] ==
'2') {
3376 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3378 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3379 (argv[i][j + 1] ==
'.')) {
3381 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3382 (argv[i][j + 1] ==
'.')) {
3384 workstring[k] = argv[i][j];
3387 workstring[k] =
'\0';
3388 optmaxdihedral = (REAL) strtod(workstring, (
char **) NULL);
3391 }
else if (argv[i][j] ==
'O') {
3392 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) {
3393 optlevel = (argv[i][j + 1] -
'0');
3396 if ((argv[i][j + 1] ==
'/') || (argv[i][j + 1] ==
',')) {
3398 if ((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'7')) {
3399 optscheme = (argv[i][j + 1] -
'0');
3403 }
else if (argv[i][j] ==
'T') {
3404 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3405 (argv[i][j + 1] ==
'.')) {
3407 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3408 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3409 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3411 workstring[k] = argv[i][j];
3414 workstring[k] =
'\0';
3415 epsilon = (REAL) strtod(workstring, (
char **) NULL);
3417 }
else if (argv[i][j] ==
'C') {
3419 }
else if (argv[i][j] ==
'Q') {
3421 }
else if (argv[i][j] ==
'V') {
3423 }
else if (argv[i][j] ==
'x') {
3424 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3425 (argv[i][j + 1] ==
'.')) {
3427 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3428 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3429 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3431 workstring[k] = argv[i][j];
3434 workstring[k] =
'\0';
3435 tetrahedraperblock = (int) strtol(workstring, (
char **) NULL, 0);
3436 if (tetrahedraperblock > 8188) {
3437 vertexperblock = tetrahedraperblock / 2;
3438 shellfaceperblock = vertexperblock / 2;
3440 tetrahedraperblock = 8188;
3443 }
else if (argv[i][j] ==
'H') {
3444 if (argv[i+1][0] !=
'-') {
3447 strncpy(hole_mesh_filename, argv[i+1], 1024 - 1);
3448 hole_mesh_filename[1024 - 1] =
'\0';
3452 }
else if (argv[i][j] ==
'K') {
3454 }
else if ((argv[i][j] ==
'h') ||
3455 (argv[i][j] ==
'?')) {
3458 printf(
"Warning: Unknown switch -%c.\n", argv[i][j]);
3463 if (startindex == 0) {
3465 strcpy(infilename,
"tetgen-tmpfile");
3467 if (infilename[0] ==
'\0') {
3470 terminatetetgen(NULL, 0);
3473 if (!strcmp(&infilename[strlen(infilename) - 5],
".node")) {
3474 infilename[strlen(infilename) - 5] =
'\0';
3476 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".poly")) {
3477 infilename[strlen(infilename) - 5] =
'\0';
3480 }
else if (!strcmp(&infilename[strlen(infilename) - 6],
".smesh")) {
3481 infilename[strlen(infilename) - 6] =
'\0';
3484 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".off")) {
3485 infilename[strlen(infilename) - 4] =
'\0';
3488 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ply")) {
3489 infilename[strlen(infilename) - 4] =
'\0';
3492 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".stl")) {
3493 infilename[strlen(infilename) - 4] =
'\0';
3496 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".mesh")) {
3497 infilename[strlen(infilename) - 5] =
'\0';
3499 if (!refine) plc = 1;
3500 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".vtk")) {
3501 infilename[strlen(infilename) - 4] =
'\0';
3504 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ele")) {
3505 infilename[strlen(infilename) - 4] =
'\0';
3508 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".neu")) {
3509 infilename[strlen(infilename) - 4] =
'\0';
3515 if (nobisect && (!plc && !refine)) {
3518 if (quality && (!plc && !refine)) {
3521 if (diagnose && !plc) {
3524 if (refine && !quality) {
3528 if (insertaddpoints && (optlevel == 0)) {
3531 if (coarsen && (optlevel == 0)) {
3536 if ((refine || plc) && weighted) {
3537 printf(
"Error: Switches -w cannot use together with -p or -r.\n");
3542 if (plc && !regionattrib) {
3551 if (refine || !plc) {
3556 if (!refine && !plc) {
3560 if (fixedvolume || varvolume) {
3563 if (!plc && !refine) {
3570 if (optmaxdihedral < 179.0) {
3572 optmaxdihedral = 179.0;
3574 optmaxdihedral = 179.999;
3577 if (optminsmtdihed < 179.999) {
3578 optminsmtdihed = 179.999;
3580 if (optminslidihed < 179.999) {
3581 optminslidihed = 179.999;
3586 strcpy(workstring, infilename);
3588 while (workstring[j] !=
'\0') {
3589 if ((workstring[j] ==
'.') && (workstring[j + 1] !=
'\0')) {
3595 if (increment > 0) {
3598 if ((workstring[j] >=
'0') && (workstring[j] <=
'9')) {
3599 meshnumber = meshnumber * 10 + (int) (workstring[j] -
'0');
3604 }
while (workstring[j] !=
'\0');
3606 if (noiterationnum) {
3607 strcpy(outfilename, infilename);
3608 }
else if (increment == 0) {
3609 strcpy(outfilename, infilename);
3610 strcat(outfilename,
".1");
3612 workstring[increment] =
'%';
3613 workstring[increment + 1] =
'd';
3614 workstring[increment + 2] =
'\0';
3615 sprintf(outfilename, workstring, meshnumber + 1);
3618 strcpy(addinfilename, infilename);
3619 strcat(addinfilename,
".a");
3621 strcpy(bgmeshfilename, infilename);
3622 strcat(bgmeshfilename,
".b");
3637 int tetgenmesh::bondtbl[12][12] = {{0,},};
3638 int tetgenmesh::enexttbl[12] = {0,};
3639 int tetgenmesh::eprevtbl[12] = {0,};
3640 int tetgenmesh::enextesymtbl[12] = {0,};
3641 int tetgenmesh::eprevesymtbl[12] = {0,};
3642 int tetgenmesh::eorgoppotbl[12] = {0,};
3643 int tetgenmesh::edestoppotbl[12] = {0,};
3644 int tetgenmesh::fsymtbl[12][12] = {{0,},};
3645 int tetgenmesh::facepivot1[12] = {0,};
3646 int tetgenmesh::facepivot2[12][12] = {{0,},};
3647 int tetgenmesh::tsbondtbl[12][6] = {{0,},};
3648 int tetgenmesh::stbondtbl[12][6] = {{0,},};
3649 int tetgenmesh::tspivottbl[12][6] = {{0,},};
3650 int tetgenmesh::stpivottbl[12][6] = {{0,},};
3655 int tetgenmesh::esymtbl[12] = {9, 6, 11, 4, 3, 7, 1, 5, 10, 0, 8, 2};
3661 int tetgenmesh:: orgpivot[12] = {7, 7, 5, 5, 6, 4, 4, 6, 5, 6, 7, 4};
3662 int tetgenmesh::destpivot[12] = {6, 4, 4, 6, 5, 6, 7, 4, 7, 7, 5, 5};
3663 int tetgenmesh::apexpivot[12] = {5, 6, 7, 4, 7, 7, 5, 5, 6, 4, 4, 6};
3664 int tetgenmesh::oppopivot[12] = {4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7};
3669 int tetgenmesh::ver2edge[12] = {0, 1, 2, 3, 3, 5, 1, 5, 4, 0, 4, 2};
3670 int tetgenmesh::edge2ver[ 6] = {0, 1, 2, 3, 8, 5};
3674 int tetgenmesh::epivot[12] = {4, 5, 2, 11, 4, 5, 2, 11, 4, 5, 2, 11};
3680 int tetgenmesh::snextpivot[6] = {2, 5, 4, 1, 0, 3};
3686 int tetgenmesh::sorgpivot [6] = {3, 4, 4, 5, 5, 3};
3687 int tetgenmesh::sdestpivot[6] = {4, 3, 5, 4, 3, 5};
3688 int tetgenmesh::sapexpivot[6] = {5, 5, 3, 3, 4, 4};
3696 void tetgenmesh::inittables()
3698 int soffset, toffset;
3703 for (i = 0; i < 12; i++) {
3704 for (j = 0; j < 12; j++) {
3705 bondtbl[i][j] = (j & 3) + (((i & 12) + (j & 12)) % 12);
3711 for (i = 0; i < 12; i++) {
3712 for (j = 0; j < 12; j++) {
3713 fsymtbl[i][j] = (j + 12 - (i & 12)) % 12;
3718 for (i = 0; i < 12; i++) {
3719 facepivot1[i] = (esymtbl[i] & 3);
3722 for (i = 0; i < 12; i++) {
3723 for (j = 0; j < 12; j++) {
3724 facepivot2[i][j] = fsymtbl[esymtbl[i]][j];
3728 for (i = 0; i < 12; i++) {
3729 enexttbl[i] = (i + 4) % 12;
3730 eprevtbl[i] = (i + 8) % 12;
3733 for (i = 0; i < 12; i++) {
3734 enextesymtbl[i] = esymtbl[enexttbl[i]];
3735 eprevesymtbl[i] = esymtbl[eprevtbl[i]];
3738 for (i = 0; i < 12; i++) {
3739 eorgoppotbl [i] = eprevtbl[esymtbl[enexttbl[i]]];
3740 edestoppotbl[i] = enexttbl[esymtbl[eprevtbl[i]]];
3744 for (i = 0; i < 12; i++) {
3745 for (j = 0; j < 6; j++) {
3747 soffset = (6 - ((i & 12) >> 1)) % 6;
3748 toffset = (12 - ((j & 6) << 1)) % 12;
3750 soffset = (i & 12) >> 1;
3751 toffset = (j & 6) << 1;
3753 tsbondtbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6);
3754 stbondtbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12);
3760 for (i = 0; i < 12; i++) {
3761 for (j = 0; j < 6; j++) {
3763 soffset = (i & 12) >> 1;
3764 toffset = (j & 6) << 1;
3766 soffset = (6 - ((i & 12) >> 1)) % 6;
3767 toffset = (12 - ((j & 6) << 1)) % 12;
3769 tspivottbl[i][j] = (j & 1) + (((j & 6) + soffset) % 6);
3770 stpivottbl[i][j] = (i & 3) + (((i & 12) + toffset) % 12);
3786 void tetgenmesh::arraypool::restart()
3800 void tetgenmesh::arraypool::poolinit(
int sizeofobject,
int log2objperblk)
3803 objectbytes = sizeofobject > 1 ? sizeofobject : 1;
3805 log2objectsperblock = log2objperblk;
3807 objectsperblock = ((int) 1) << log2objectsperblock;
3808 objectsperblockmark = objectsperblock - 1;
3813 toparray = (
char **) NULL;
3826 tetgenmesh::arraypool::arraypool(
int sizeofobject,
int log2objperblk)
3828 poolinit(sizeofobject, log2objperblk);
3831 tetgenmesh::arraypool::~arraypool()
3836 if (toparray != (
char **) NULL) {
3838 for (i = 0; i < toparraylen; i++) {
3840 if (toparray[i] != (
char *) NULL) {
3842 free((
void *) toparray[i]);
3846 free((
void *) toparray);
3850 toparray = (
char **) NULL;
3868 char* tetgenmesh::arraypool::getblock(
int objectindex)
3877 topindex = objectindex >> log2objectsperblock;
3879 if (toparray == (
char **) NULL) {
3882 newsize = topindex + 128;
3883 toparray = (
char **) malloc((
size_t) (newsize *
sizeof(
char *)));
3884 toparraylen = newsize;
3885 for (i = 0; i < newsize; i++) {
3886 toparray[i] = (
char *) NULL;
3889 totalmemory = newsize * (uintptr_t)
sizeof(
char *);
3890 }
else if (topindex >= toparraylen) {
3892 newsize = 3 * toparraylen;
3893 if (topindex >= newsize) {
3894 newsize = topindex + 128;
3898 newarray = (
char **) malloc((
size_t) (newsize *
sizeof(
char *)));
3899 for (i = 0; i < toparraylen; i++) {
3900 newarray[i] = toparray[i];
3902 for (i = toparraylen; i < newsize; i++) {
3903 newarray[i] = (
char *) NULL;
3907 totalmemory += (newsize - toparraylen) *
sizeof(
char *);
3908 toparray = newarray;
3909 toparraylen = newsize;
3913 block = toparray[topindex];
3914 if (block == (
char *) NULL) {
3916 block = (
char *) malloc((
size_t) (objectsperblock * objectbytes));
3917 toparray[topindex] = block;
3919 totalmemory += objectsperblock * objectbytes;
3933 void* tetgenmesh::arraypool::lookup(
int objectindex)
3939 if (toparray == (
char **) NULL) {
3940 return (
void *) NULL;
3944 topindex = objectindex >> log2objectsperblock;
3946 if (topindex >= toparraylen) {
3947 return (
void *) NULL;
3951 block = toparray[topindex];
3952 if (block == (
char *) NULL) {
3953 return (
void *) NULL;
3959 return (
void *)(block + (objectindex & (objectsperblock - 1)) * objectbytes);
3970 int tetgenmesh::arraypool::newindex(
void **newptr)
3973 int newindex = objects;
3974 *newptr = (
void *) (getblock(objects) +
3975 (objects & (objectsperblock - 1)) * objectbytes);
3988 tetgenmesh::memorypool::memorypool()
3990 firstblock = nowblock = (
void **) NULL;
3991 nextitem = (
void *) NULL;
3992 deaditemstack = (
void *) NULL;
3993 pathblock = (
void **) NULL;
3994 pathitem = (
void *) NULL;
3996 itembytes = itemwords = 0;
3998 items = maxitems = 0l;
3999 unallocateditems = 0;
4003 tetgenmesh::memorypool::memorypool(
int bytecount,
int itemcount,
int wsize,
4006 poolinit(bytecount, itemcount, wsize, alignment);
4015 tetgenmesh::memorypool::~memorypool()
4017 while (firstblock != (
void **) NULL) {
4018 nowblock = (
void **) *(firstblock);
4020 firstblock = nowblock;
4040 void tetgenmesh::memorypool::poolinit(
int bytecount,
int itemcount,
int wordsize,
4048 if (alignment > wordsize) {
4049 alignbytes = alignment;
4051 alignbytes = wordsize;
4053 if ((
int)
sizeof(
void *) > alignbytes) {
4054 alignbytes = (int)
sizeof(
void *);
4056 itemwords = ((bytecount + alignbytes - 1) / alignbytes)
4057 * (alignbytes / wordsize);
4058 itembytes = itemwords * wordsize;
4059 itemsperblock = itemcount;
4064 firstblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
4066 if (firstblock == (
void **) NULL) {
4067 terminatetetgen(NULL, 1);
4070 *(firstblock) = (
void *) NULL;
4084 void tetgenmesh::memorypool::restart()
4092 nowblock = firstblock;
4094 alignptr = (uintptr_t) (nowblock + 1);
4097 (alignptr + (uintptr_t) alignbytes -
4098 (alignptr % (uintptr_t) alignbytes));
4100 unallocateditems = itemsperblock;
4102 deaditemstack = (
void *) NULL;
4111 void* tetgenmesh::memorypool::alloc()
4119 if (deaditemstack != (
void *) NULL) {
4120 newitem = deaditemstack;
4121 deaditemstack = * (
void **) deaditemstack;
4124 if (unallocateditems == 0) {
4126 if (*nowblock == (
void *) NULL) {
4128 newblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
4130 if (newblock == (
void **) NULL) {
4131 terminatetetgen(NULL, 1);
4133 *nowblock = (
void *) newblock;
4135 *newblock = (
void *) NULL;
4138 nowblock = (
void **) *nowblock;
4141 alignptr = (uintptr_t) (nowblock + 1);
4144 (alignptr + (uintptr_t) alignbytes -
4145 (alignptr % (uintptr_t) alignbytes));
4147 unallocateditems = itemsperblock;
4152 nextitem = (
void *) ((uintptr_t) nextitem + itembytes);
4168 void tetgenmesh::memorypool::dealloc(
void *dyingitem)
4171 *((
void **) dyingitem) = deaditemstack;
4172 deaditemstack = dyingitem;
4184 void tetgenmesh::memorypool::traversalinit()
4189 pathblock = firstblock;
4191 alignptr = (uintptr_t) (pathblock + 1);
4194 (alignptr + (uintptr_t) alignbytes -
4195 (alignptr % (uintptr_t) alignbytes));
4197 pathitemsleft = itemsperblock;
4212 void* tetgenmesh::memorypool::traverse()
4218 if (pathitem == nextitem) {
4219 return (
void *) NULL;
4222 if (pathitemsleft == 0) {
4224 pathblock = (
void **) *pathblock;
4226 alignptr = (uintptr_t) (pathblock + 1);
4229 (alignptr + (uintptr_t) alignbytes -
4230 (alignptr % (uintptr_t) alignbytes));
4232 pathitemsleft = itemsperblock;
4236 pathitem = (
void *) ((uintptr_t) pathitem + itembytes);
4251 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
4256 if (b->verbose > 1) {
4257 printf(
" Constructing mapping from indices to points.\n");
4260 idx2verlist =
new point[points->items + 1];
4262 points->traversalinit();
4263 pointloop = pointtraverse();
4264 idx = in->firstnumber;
4265 while (pointloop != (point) NULL) {
4266 idx2verlist[idx++] = pointloop;
4267 pointloop = pointtraverse();
4285 void tetgenmesh::makepoint2submap(memorypool* pool,
int*& idx2faclist,
4286 face*& facperverlist)
4291 if (b->verbose > 1) {
4292 printf(
" Making a map from points to subfaces.\n");
4296 idx2faclist =
new int[points->items + 1];
4297 for (i = 0; i < points->items + 1; i++) idx2faclist[i] = 0;
4300 pool->traversalinit();
4301 shloop.sh = shellfacetraverse(pool);
4302 while (shloop.sh != (shellface *) NULL) {
4304 j = pointmark((point) shloop.sh[3]) - in->firstnumber;
4306 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4309 if (shloop.sh[5] != NULL) {
4310 j = pointmark((point) shloop.sh[5]) - in->firstnumber;
4313 shloop.sh = shellfacetraverse(pool);
4319 for (i = 0; i < points->items; i++) {
4320 k = idx2faclist[i + 1];
4321 idx2faclist[i + 1] = idx2faclist[i] + j;
4326 facperverlist =
new face[idx2faclist[i]];
4329 pool->traversalinit();
4330 shloop.sh = shellfacetraverse(pool);
4331 while (shloop.sh != (shellface *) NULL) {
4332 j = pointmark((point) shloop.sh[3]) - in->firstnumber;
4334 facperverlist[idx2faclist[j]] = shloop;
4337 if (shloop.sh[5] != NULL) {
4338 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4340 facperverlist[idx2faclist[j]] = shloop;
4342 j = pointmark((point) shloop.sh[5]) - in->firstnumber;
4344 facperverlist[idx2faclist[j]] = shloop;
4347 j = pointmark((point) shloop.sh[4]) - in->firstnumber;
4349 facperverlist[idx2faclist[j]] = shloop;
4352 shloop.sh = shellfacetraverse(pool);
4356 for (i = points->items - 1; i >= 0; i--) {
4357 idx2faclist[i + 1] = idx2faclist[i];
4368 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
4372 dyingtetrahedron[4] = (tetrahedron) NULL;
4375 if (dyingtetrahedron[8] != NULL) {
4376 tet2segpool->dealloc((shellface *) dyingtetrahedron[8]);
4378 if (dyingtetrahedron[9] != NULL) {
4379 tet2subpool->dealloc((shellface *) dyingtetrahedron[9]);
4382 tetrahedrons->dealloc((
void *) dyingtetrahedron);
4391 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
4393 tetrahedron *newtetrahedron;
4396 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
4397 if (newtetrahedron == (tetrahedron *) NULL) {
4398 return (tetrahedron *) NULL;
4400 }
while ((newtetrahedron[4] == (tetrahedron) NULL) ||
4401 ((point) newtetrahedron[7] == dummypoint));
4402 return newtetrahedron;
4405 tetgenmesh::tetrahedron* tetgenmesh::alltetrahedrontraverse()
4407 tetrahedron *newtetrahedron;
4410 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
4411 if (newtetrahedron == (tetrahedron *) NULL) {
4412 return (tetrahedron *) NULL;
4414 }
while (newtetrahedron[4] == (tetrahedron) NULL);
4415 return newtetrahedron;
4425 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
4429 dyingsh[3] = (shellface) NULL;
4430 pool->dealloc((
void *) dyingsh);
4440 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
4442 shellface *newshellface;
4445 newshellface = (shellface *) pool->traverse();
4446 if (newshellface == (shellface *) NULL) {
4447 return (shellface *) NULL;
4449 }
while (newshellface[3] == (shellface) NULL);
4450 return newshellface;
4460 void tetgenmesh::pointdealloc(point dyingpoint)
4464 setpointtype(dyingpoint, DEADVERTEX);
4465 points->dealloc((
void *) dyingpoint);
4474 tetgenmesh::point tetgenmesh::pointtraverse()
4479 newpoint = (point) points->traverse();
4480 if (newpoint == (point) NULL) {
4481 return (point) NULL;
4483 }
while (pointtype(newpoint) == DEADVERTEX);
4493 void tetgenmesh::maketetrahedron(triface *newtet)
4495 newtet->tet = (tetrahedron *) tetrahedrons->alloc();
4498 newtet->tet[0] = NULL;
4499 newtet->tet[1] = NULL;
4500 newtet->tet[2] = NULL;
4501 newtet->tet[3] = NULL;
4503 newtet->tet[4] = NULL;
4504 newtet->tet[5] = NULL;
4505 newtet->tet[6] = NULL;
4506 newtet->tet[7] = NULL;
4508 newtet->tet[8] = NULL;
4509 newtet->tet[9] = NULL;
4511 setelemmarker(newtet->tet, 0);
4512 for (
int i = 0; i < numelemattrib; i++) {
4513 setelemattribute(newtet->tet, i, 0.0);
4516 setvolumebound(newtet->tet, -1.0);
4530 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
4532 newface->sh = (shellface *) pool->alloc();
4535 newface->sh[0] = NULL;
4536 newface->sh[1] = NULL;
4537 newface->sh[2] = NULL;
4539 newface->sh[3] = NULL;
4540 newface->sh[4] = NULL;
4541 newface->sh[5] = NULL;
4543 newface->sh[6] = NULL;
4544 newface->sh[7] = NULL;
4545 newface->sh[8] = NULL;
4547 newface->sh[9] = NULL;
4548 newface->sh[10] = NULL;
4549 if (checkconstraints) {
4551 setareabound(*newface, 0.0);
4554 setshellmark(*newface, 0);
4556 ((
int *) (newface->sh))[shmarkindex + 1] = 0;
4557 if (useinsertradius) {
4558 setfacetindex(*newface, 0);
4570 void tetgenmesh::makepoint(point* pnewpoint,
enum verttype vtype)
4574 *pnewpoint = (point) points->alloc();
4577 for (i = 0; i < numpointattrib; i++) {
4578 (*pnewpoint)[3 + i] = 0.0;
4581 for (i = 0; i < sizeoftensor; i++) {
4582 (*pnewpoint)[pointmtrindex + i] = 0.0;
4584 setpoint2tet(*pnewpoint, NULL);
4585 setpoint2ppt(*pnewpoint, NULL);
4586 if (b->plc || b->refine) {
4588 setpoint2sh(*pnewpoint, NULL);
4589 if (b->metric && (bgm != NULL)) {
4590 setpoint2bgmtet(*pnewpoint, NULL);
4594 setpointmark(*pnewpoint, (
int) (points->items) - (!in->firstnumber));
4596 ((
int *) (*pnewpoint))[pointmarkindex + 1] = 0;
4598 setpointtype(*pnewpoint, vtype);
4612 void tetgenmesh::initializepools()
4614 int pointsize = 0, elesize = 0, shsize = 0;
4618 printf(
" Initializing memorypools.\n");
4619 printf(
" tetrahedron per block: %d.\n", b->tetrahedraperblock);
4627 numpointattrib = in->numberofpointattributes;
4629 if (bgm->in->numberofpointattributes > numpointattrib) {
4630 numpointattrib = bgm->in->numberofpointattributes;
4633 if (addin != NULL) {
4634 if (addin->numberofpointattributes > numpointattrib) {
4635 numpointattrib = addin->numberofpointattributes;
4638 if (b->weighted || b->flipinsert) {
4641 if (numpointattrib == 0) {
4647 if (in->segmentconstraintlist || in->facetconstraintlist) {
4648 checkconstraints = 1;
4650 if (b->plc || b->refine) {
4653 if (!b->nobisect || checkconstraints) {
4654 useinsertradius = 1;
4662 pointmtrindex = 5 + numpointattrib;
4665 pointparamindex = pointmtrindex - 2;
4667 pointmtrindex = 3 + numpointattrib;
4674 sizeoftensor = (bgm->in != (
tetgenio *) NULL) ?
4675 bgm->in->numberofpointmtrs : in->numberofpointmtrs;
4678 sizeoftensor = in->numberofpointmtrs;
4681 sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
4684 sizeoftensor = b->quality ? 1 : 0;
4686 if (useinsertradius) {
4691 pointinsradiusindex = pointmtrindex + sizeoftensor - 1;
4695 point2simindex = ((pointmtrindex + sizeoftensor) *
sizeof(REAL)
4696 +
sizeof(tetrahedron) - 1) /
sizeof(tetrahedron);
4697 if (b->plc || b->refine || b->voroout) {
4702 if (b->metric && (bgm != (
tetgenmesh *) NULL)) {
4704 pointsize = (point2simindex + 4) *
sizeof(tetrahedron);
4706 pointsize = (point2simindex + 3) *
sizeof(tetrahedron);
4712 pointsize = (point2simindex + 2) *
sizeof(tetrahedron);
4716 pointmarkindex = (pointsize +
sizeof(int) - 1) /
sizeof(int);
4721 pointsize = (pointmarkindex + 2 + (b->psc ? 1 : 0)) *
sizeof(tetrahedron);
4724 points =
new memorypool(pointsize, b->vertexperblock,
sizeof(REAL), 0);
4727 printf(
" Size of a point: %d bytes.\n", points->itembytes);
4731 dummypoint = (point)
new char[pointsize];
4733 dummypoint[0] = 0.0;
4734 dummypoint[1] = 0.0;
4735 dummypoint[2] = 0.0;
4736 for (i = 0; i < numpointattrib; i++) {
4737 dummypoint[3 + i] = 0.0;
4740 for (i = 0; i < sizeoftensor; i++) {
4741 dummypoint[pointmtrindex + i] = 0.0;
4743 setpoint2tet(dummypoint, NULL);
4744 setpoint2ppt(dummypoint, NULL);
4745 if (b->plc || b->psc || b->refine) {
4747 setpoint2sh(dummypoint, NULL);
4748 if (b->metric && (bgm != NULL)) {
4749 setpoint2bgmtet(dummypoint, NULL);
4753 setpointmark(dummypoint, -1);
4755 ((
int *) (dummypoint))[pointmarkindex + 1] = 0;
4757 setpointtype(dummypoint, UNUSEDVERTEX);
4775 elesize = 12 *
sizeof(tetrahedron);
4779 if (!(
sizeof(
int) <=
sizeof(tetrahedron)) ||
4780 ((
sizeof(tetrahedron) %
sizeof(
int)))) {
4781 terminatetetgen(
this, 2);
4783 elemmarkerindex = (elesize -
sizeof(tetrahedron)) /
sizeof(int);
4787 numelemattrib = in->numberoftetrahedronattributes + (b->regionattrib > 0);
4791 elemattribindex = (elesize +
sizeof(REAL) - 1) /
sizeof(REAL);
4794 volumeboundindex = elemattribindex + numelemattrib;
4798 elesize = (volumeboundindex + 1) *
sizeof(REAL);
4799 }
else if (numelemattrib > 0) {
4800 elesize = volumeboundindex *
sizeof(REAL);
4805 tetrahedrons =
new memorypool(elesize, b->tetrahedraperblock,
sizeof(
void *),
4809 printf(
" Size of a tetrahedron: %d (%d) bytes.\n", elesize,
4810 tetrahedrons->itembytes);
4813 if (b->plc || b->refine) {
4817 shsize = 11 *
sizeof(shellface);
4820 areaboundindex = (shsize +
sizeof(REAL) - 1) /
sizeof(REAL);
4823 if (checkconstraints) {
4824 shsize = (areaboundindex + 1) *
sizeof(REAL);
4826 shsize = areaboundindex *
sizeof(REAL);
4830 shmarkindex = (shsize +
sizeof(int) - 1) /
sizeof(int);
4834 shsize = (shmarkindex + 2 + useinsertradius) *
sizeof(shellface);
4839 subfaces =
new memorypool(shsize, b->shellfaceperblock,
sizeof(
void *), 8);
4842 printf(
" Size of a shellface: %d (%d) bytes.\n", shsize,
4843 subfaces->itembytes);
4848 subsegs =
new memorypool(shsize, b->shellfaceperblock,
sizeof(
void *), 8);
4851 tet2segpool =
new memorypool(6 *
sizeof(shellface), b->shellfaceperblock,
4854 tet2subpool =
new memorypool(4 *
sizeof(shellface), b->shellfaceperblock,
4858 subsegstack =
new arraypool(
sizeof(face), 10);
4859 subfacstack =
new arraypool(
sizeof(face), 10);
4860 subvertstack =
new arraypool(
sizeof(point), 8);
4863 caveshlist =
new arraypool(
sizeof(face), 8);
4864 caveshbdlist =
new arraypool(
sizeof(face), 8);
4865 cavesegshlist =
new arraypool(
sizeof(face), 4);
4867 cavetetshlist =
new arraypool(
sizeof(face), 8);
4868 cavetetseglist =
new arraypool(
sizeof(face), 8);
4869 caveencshlist =
new arraypool(
sizeof(face), 8);
4870 caveencseglist =
new arraypool(
sizeof(face), 8);
4874 flippool =
new memorypool(
sizeof(badface), 1024,
sizeof(
void *), 0);
4875 unflipqueue =
new arraypool(
sizeof(badface), 10);
4878 cavetetlist =
new arraypool(
sizeof(triface), 10);
4879 cavebdrylist =
new arraypool(
sizeof(triface), 10);
4880 caveoldtetlist =
new arraypool(
sizeof(triface), 10);
4881 cavetetvertlist =
new arraypool(
sizeof(point), 10);
4893 REAL tetgenmesh::PI = 3.14159265358979323846264338327950288419716939937510582;
4911 REAL tetgenmesh::insphere_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe)
4915 sign = insphere(pa, pb, pc, pd, pe);
4921 point pt[5], swappt;
4940 for (i = 0; i < n; i++) {
4941 if (pointmark(pt[i]) > pointmark(pt[i+1])) {
4942 swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt;
4947 }
while (count > 0);
4949 oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
4952 if ((swaps % 2) != 0) oriA = -oriA;
4956 oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
4958 terminatetetgen(
this, 2);
4961 if ((swaps % 2) != 0) oriB = -oriB;
4982 REAL tetgenmesh::orient4d_s(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
4983 REAL aheight, REAL bheight, REAL cheight,
4984 REAL dheight, REAL eheight)
4988 sign = orient4d(pa, pb, pc, pd, pe,
4989 aheight, bheight, cheight, dheight, eheight);
4995 point pt[5], swappt;
5014 for (i = 0; i < n; i++) {
5015 if (pointmark(pt[i]) > pointmark(pt[i+1])) {
5016 swappt = pt[i]; pt[i] = pt[i+1]; pt[i+1] = swappt;
5021 }
while (count > 0);
5023 oriA = orient3d(pt[1], pt[2], pt[3], pt[4]);
5026 if ((swaps % 2) != 0) oriA = -oriA;
5030 oriB = -orient3d(pt[0], pt[2], pt[3], pt[4]);
5032 terminatetetgen(
this, 2);
5035 if ((swaps % 2) != 0) oriB = -oriB;
5061 #define SETVECTOR3(V, a0, a1, a2) (V)[0] = (a0); (V)[1] = (a1); (V)[2] = (a2) 5063 #define SWAP2(a0, a1, tmp) (tmp) = (a0); (a0) = (a1); (a1) = (tmp) 5065 int tetgenmesh::tri_edge_2d(point A, point B, point C, point P, point Q,
5066 point R,
int level,
int *types,
int *pos)
5072 REAL s1, s2, s3, s4;
5080 facenormal(A, B, C, n, 1, NULL);
5081 len = sqrt(dot(n, n));
5086 len = distance(A, B);
5087 len += distance(B, C);
5088 len += distance(C, A);
5091 R[0] = A[0] + len * n[0];
5092 R[1] = A[1] + len * n[1];
5093 R[2] = A[2] + len * n[2];
5104 sA = orient3d(P, Q, R, A);
5105 sB = orient3d(P, Q, R, B);
5106 sC = orient3d(P, Q, R, C);
5116 SETVECTOR3(U, A, B, C);
5117 SETVECTOR3(V, P, Q, R);
5118 SETVECTOR3(pu, 0, 1, 2);
5119 SETVECTOR3(pv, 0, 1, 2);
5122 SETVECTOR3(U, A, B, C);
5123 SETVECTOR3(V, P, Q, R);
5124 SETVECTOR3(pu, 0, 1, 2);
5125 SETVECTOR3(pv, 0, 1, 2);
5132 SETVECTOR3(U, C, A, B);
5133 SETVECTOR3(V, P, Q, R);
5134 SETVECTOR3(pu, 2, 0, 1);
5135 SETVECTOR3(pv, 0, 1, 2);
5139 SETVECTOR3(U, B, C, A);
5140 SETVECTOR3(V, Q, P, R);
5141 SETVECTOR3(pu, 1, 2, 0);
5142 SETVECTOR3(pv, 1, 0, 2);
5145 SETVECTOR3(U, C, A, B);
5146 SETVECTOR3(V, P, Q, R);
5147 SETVECTOR3(pu, 2, 0, 1);
5148 SETVECTOR3(pv, 0, 1, 2);
5154 SETVECTOR3(U, C, A, B);
5155 SETVECTOR3(V, P, Q, R);
5156 SETVECTOR3(pu, 2, 0, 1);
5157 SETVECTOR3(pv, 0, 1, 2);
5161 SETVECTOR3(U, B, C, A);
5162 SETVECTOR3(V, Q, P, R);
5163 SETVECTOR3(pu, 1, 2, 0);
5164 SETVECTOR3(pv, 1, 0, 2);
5167 SETVECTOR3(U, B, C, A);
5168 SETVECTOR3(V, Q, P, R);
5169 SETVECTOR3(pu, 1, 2, 0);
5170 SETVECTOR3(pv, 1, 0, 2);
5180 SETVECTOR3(U, B, C, A);
5181 SETVECTOR3(V, P, Q, R);
5182 SETVECTOR3(pu, 1, 2, 0);
5183 SETVECTOR3(pv, 0, 1, 2);
5187 SETVECTOR3(U, C, A, B);
5188 SETVECTOR3(V, Q, P, R);
5189 SETVECTOR3(pu, 2, 0, 1);
5190 SETVECTOR3(pv, 1, 0, 2);
5193 SETVECTOR3(U, C, A, B);
5194 SETVECTOR3(V, Q, P, R);
5195 SETVECTOR3(pu, 2, 0, 1);
5196 SETVECTOR3(pv, 1, 0, 2);
5203 SETVECTOR3(U, A, B, C);
5204 SETVECTOR3(V, Q, P, R);
5205 SETVECTOR3(pu, 0, 1, 2);
5206 SETVECTOR3(pv, 1, 0, 2);
5212 SETVECTOR3(U, A, B, C);
5213 SETVECTOR3(V, Q, P, R);
5214 SETVECTOR3(pu, 0, 1, 2);
5215 SETVECTOR3(pv, 1, 0, 2);
5221 SETVECTOR3(U, B, C, A);
5222 SETVECTOR3(V, P, Q, R);
5223 SETVECTOR3(pu, 1, 2, 0);
5224 SETVECTOR3(pv, 0, 1, 2);
5228 SETVECTOR3(U, C, A, B);
5229 SETVECTOR3(V, Q, P, R);
5230 SETVECTOR3(pu, 2, 0, 1);
5231 SETVECTOR3(pv, 1, 0, 2);
5234 SETVECTOR3(U, B, C, A);
5235 SETVECTOR3(V, P, Q, R);
5236 SETVECTOR3(pu, 1, 2, 0);
5237 SETVECTOR3(pv, 0, 1, 2);
5246 SETVECTOR3(U, B, C, A);
5247 SETVECTOR3(V, P, Q, R);
5248 SETVECTOR3(pu, 1, 2, 0);
5249 SETVECTOR3(pv, 0, 1, 2);
5253 SETVECTOR3(U, A, B, C);
5254 SETVECTOR3(V, P, Q, R);
5255 SETVECTOR3(pu, 0, 1, 2);
5256 SETVECTOR3(pv, 0, 1, 2);
5259 SETVECTOR3(U, C, A, B);
5260 SETVECTOR3(V, Q, P, R);
5261 SETVECTOR3(pu, 2, 0, 1);
5262 SETVECTOR3(pv, 1, 0, 2);
5269 SETVECTOR3(U, A, B, C);
5270 SETVECTOR3(V, Q, P, R);
5271 SETVECTOR3(pu, 0, 1, 2);
5272 SETVECTOR3(pv, 1, 0, 2);
5276 SETVECTOR3(U, B, C, A);
5277 SETVECTOR3(V, Q, P, R);
5278 SETVECTOR3(pu, 1, 2, 0);
5279 SETVECTOR3(pv, 1, 0, 2);
5282 SETVECTOR3(U, C, A, B);
5283 SETVECTOR3(V, P, Q, R);
5284 SETVECTOR3(pu, 2, 0, 1);
5285 SETVECTOR3(pv, 0, 1, 2);
5291 SETVECTOR3(U, A, B, C);
5292 SETVECTOR3(V, Q, P, R);
5293 SETVECTOR3(pu, 0, 1, 2);
5294 SETVECTOR3(pv, 1, 0, 2);
5298 SETVECTOR3(U, A, B, C);
5299 SETVECTOR3(V, P, Q, R);
5300 SETVECTOR3(pu, 0, 1, 2);
5301 SETVECTOR3(pv, 0, 1, 2);
5306 SETVECTOR3(U, A, B, C);
5307 SETVECTOR3(V, P, Q, R);
5308 SETVECTOR3(pu, 0, 1, 2);
5309 SETVECTOR3(pv, 0, 1, 2);
5318 s1 = orient3d(U[0], U[2], R, V[1]);
5319 s2 = orient3d(U[1], U[2], R, V[0]);
5336 types[0] = (int) SHAREVERT;
5339 types[1] = (int) DISJOINT;
5343 types[0] = (int) SHAREVERT;
5346 types[1] = (int) DISJOINT;
5349 types[0] = (int) ACROSSVERT;
5352 types[1] = (int) DISJOINT;
5358 s3 = orient3d(U[0], U[2], R, V[0]);
5359 s4 = orient3d(U[1], U[2], R, V[1]);
5366 types[0] = (int) ACROSSEDGE;
5369 types[1] = (int) TOUCHFACE;
5375 types[0] = (int) ACROSSEDGE;
5378 types[1] = (int) TOUCHEDGE;
5383 types[0] = (int) ACROSSEDGE;
5386 types[1] = (int) ACROSSEDGE;
5395 types[0] = (int) TOUCHEDGE;
5398 types[1] = (int) TOUCHFACE;
5404 types[0] = (int) TOUCHEDGE;
5407 types[1] = (int) TOUCHEDGE;
5412 types[0] = (int) TOUCHEDGE;
5415 types[1] = (int) ACROSSEDGE;
5424 types[0] = (int) TOUCHFACE;
5427 types[1] = (int) TOUCHFACE;
5433 types[0] = (int) TOUCHFACE;
5436 types[1] = (int) TOUCHEDGE;
5441 types[0] = (int) TOUCHFACE;
5444 types[1] = (int) ACROSSEDGE;
5451 types[0] = (int) TOUCHEDGE;
5454 types[1] = (int) DISJOINT;
5460 types[0] = (int) TOUCHEDGE;
5463 types[1] = (int) DISJOINT;
5465 }
else if (z1 == 2) {
5470 types[0] = (int) ACROSSVERT;
5473 types[1] = (int) TOUCHFACE;
5479 types[0] = (int) ACROSSVERT;
5482 types[1] = (int) TOUCHEDGE;
5487 types[0] = (int) ACROSSVERT;
5490 types[1] = (int) ACROSSEDGE;
5499 types[0] = (int) SHAREVERT;
5502 types[1] = (int) TOUCHFACE;
5508 types[0] = (int) SHAREVERT;
5511 types[1] = (int) TOUCHEDGE;
5516 types[0] = (int) SHAREVERT;
5519 types[1] = (int) ACROSSEDGE;
5528 types[0] = (int) TOUCHFACE;
5531 types[0] = (int) TOUCHFACE;
5537 types[0] = (int) TOUCHFACE;
5540 types[0] = (int) TOUCHEDGE;
5545 types[0] = (int) TOUCHFACE;
5548 types[0] = (int) ACROSSEDGE;
5555 types[0] = (int) TOUCHEDGE;
5558 types[1] = (int) DISJOINT;
5564 types[0] = (int) SHAREVERT;
5567 types[1] = (int) DISJOINT;
5569 }
else if (z1 == 3) {
5574 types[0] = (int) ACROSSVERT;
5577 types[1] = (int) TOUCHEDGE;
5583 types[0] = (int) ACROSSVERT;
5586 types[1] = (int) SHAREVERT;
5591 types[0] = (int) ACROSSVERT;
5594 types[1] = (int) ACROSSVERT;
5603 types[0] = (int) SHAREVERT;
5606 types[1] = (int) TOUCHEDGE;
5612 types[0] = (int) SHAREEDGE;
5615 types[1] = (int) DISJOINT;
5618 types[0] = (int) SHAREVERT;
5621 types[1] = (int) ACROSSVERT;
5630 types[0] = (int) TOUCHEDGE;
5633 types[1] = (int) TOUCHEDGE;
5639 types[0] = (int) TOUCHEDGE;
5642 types[1] = (int) SHAREVERT;
5647 types[0] = (int) TOUCHEDGE;
5650 types[1] = (int) ACROSSVERT;
5657 types[0] = (int) SHAREVERT;
5660 types[1] = (int) DISJOINT;
5666 types[0] = (int) SHAREVERT;
5669 types[1] = (int) DISJOINT;
5676 int tetgenmesh::tri_edge_tail(point A,point B,point C,point P,point Q,point R,
5677 REAL sP,REAL sQ,
int level,
int *types,
int *pos)
5690 SETVECTOR3(U, A, B, C);
5691 SETVECTOR3(V, P, Q, R);
5692 SETVECTOR3(pu, 0, 1, 2);
5693 SETVECTOR3(pv, 0, 1, 2);
5696 SETVECTOR3(U, A, B, C);
5697 SETVECTOR3(V, P, Q, R);
5698 SETVECTOR3(pu, 0, 1, 2);
5699 SETVECTOR3(pv, 0, 1, 2);
5706 SETVECTOR3(U, A, B, C);
5707 SETVECTOR3(V, Q, P, R);
5708 SETVECTOR3(pu, 0, 1, 2);
5709 SETVECTOR3(pv, 1, 0, 2);
5715 SETVECTOR3(U, B, A, C);
5716 SETVECTOR3(V, P, Q, R);
5717 SETVECTOR3(pu, 1, 0, 2);
5718 SETVECTOR3(pv, 0, 1, 2);
5724 SETVECTOR3(U, A, B, C);
5725 SETVECTOR3(V, Q, P, R);
5726 SETVECTOR3(pu, 0, 1, 2);
5727 SETVECTOR3(pv, 1, 0, 2);
5731 SETVECTOR3(U, B, A, C);
5732 SETVECTOR3(V, Q, P, R);
5733 SETVECTOR3(pu, 1, 0, 2);
5734 SETVECTOR3(pv, 1, 0, 2);
5746 return tri_edge_2d(A, B, C, P, Q, R, level, types, pos);
5749 s1 = orient3d(U[0], U[1], V[0], V[1]);
5754 s2 = orient3d(U[1], U[2], V[0], V[1]);
5759 s3 = orient3d(U[2], U[0], V[0], V[1]);
5768 types[1] = (int) DISJOINT;
5775 types[0] = (int) ACROSSFACE;
5780 types[0] = (int) ACROSSEDGE;
5787 types[0] = (int) ACROSSEDGE;
5792 types[0] = (int) ACROSSVERT;
5801 types[0] = (int) ACROSSEDGE;
5806 types[0] = (int) ACROSSVERT;
5813 types[0] = (int) ACROSSVERT;
5824 types[0] = (int) TOUCHFACE;
5829 types[0] = (int) TOUCHEDGE;
5836 types[0] = (int) TOUCHEDGE;
5841 types[0] = (int) SHAREVERT;
5850 types[0] = (int) TOUCHEDGE;
5855 types[0] = (int) SHAREVERT;
5862 types[0] = (int) SHAREVERT;
5874 int tetgenmesh::tri_edge_test(point A, point B, point C, point P, point Q,
5875 point R,
int level,
int *types,
int *pos)
5880 sP = orient3d(A, B, C, P);
5881 sQ = orient3d(A, B, C, Q);
5883 return tri_edge_tail(A, B, C, P, Q, R, sP, sQ, level, types, pos);
5896 int tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B, REAL* C, REAL* P,
5897 REAL* Q, REAL s_p, REAL s_q)
5899 int types[2], pos[4];
5902 ni = tri_edge_tail(A, B, C, P, Q, NULL, s_p, s_q, 1, types, pos);
5907 if (types[0] == (
int) SHAREVERT) {
5908 return (
int) SHAREVERT;
5910 return (
int) INTERSECT;
5912 }
else if (ni == 4) {
5914 if (types[0] == (
int) SHAREVERT) {
5915 if (types[1] == (
int) DISJOINT) {
5916 return (
int) SHAREVERT;
5918 return (
int) INTERSECT;
5921 if (types[0] == (
int) SHAREEDGE) {
5922 return (
int) SHAREEDGE;
5924 return (
int) INTERSECT;
5930 return (
int) DISJOINT;
5933 int tetgenmesh::tri_tri_inter(REAL* A,REAL* B,REAL* C,REAL* O,REAL* P,REAL* Q)
5938 s_o = orient3d(A, B, C, O);
5939 s_p = orient3d(A, B, C, P);
5940 s_q = orient3d(A, B, C, Q);
5941 if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
5946 s_a = orient3d(O, P, Q, A);
5947 s_b = orient3d(O, P, Q, B);
5948 s_c = orient3d(O, P, Q, C);
5949 if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
5954 int abcop, abcpq, abcqo;
5957 abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
5958 if (abcop == (
int) INTERSECT) {
5959 return (
int) INTERSECT;
5960 }
else if (abcop == (
int) SHAREEDGE) {
5963 abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
5964 if (abcpq == (
int) INTERSECT) {
5965 return (
int) INTERSECT;
5966 }
else if (abcpq == (
int) SHAREEDGE) {
5969 abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
5970 if (abcqo == (
int) INTERSECT) {
5971 return (
int) INTERSECT;
5972 }
else if (abcqo == (
int) SHAREEDGE) {
5975 if (shareedge == 3) {
5977 return (
int) SHAREFACE;
5981 int opqab, opqbc, opqca;
5983 opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
5984 if (opqab == (
int) INTERSECT) {
5985 return (
int) INTERSECT;
5987 opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
5988 if (opqbc == (
int) INTERSECT) {
5989 return (
int) INTERSECT;
5991 opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
5992 if (opqca == (
int) INTERSECT) {
5993 return (
int) INTERSECT;
5998 if (abcop == (
int) SHAREEDGE) {
6000 return (
int) SHAREEDGE;
6002 if (abcpq == (
int) SHAREEDGE) {
6004 return (
int) SHAREEDGE;
6006 if (abcqo == (
int) SHAREEDGE) {
6008 return (
int) SHAREEDGE;
6012 if (abcop == (
int) SHAREVERT) {
6013 return (
int) SHAREVERT;
6015 if (abcpq == (
int) SHAREVERT) {
6017 return (
int) SHAREVERT;
6021 return (
int) DISJOINT;
6048 bool tetgenmesh::lu_decmp(REAL lu[4][4],
int n,
int* ps, REAL* d,
int N)
6051 REAL pivot, biggest, mult, tempf;
6057 for (i = N; i < n + N; i++) {
6060 for (j = N; j < n + N; j++)
6061 if (biggest < (tempf = fabs(lu[i][j])))
6064 scales[i] = 1.0 / biggest;
6072 for (k = N; k < n + N - 1; k++) {
6075 for (i = k; i < n + N; i++) {
6076 if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
6081 if (biggest == 0.0) {
6084 if (pivotindex != k) {
6086 ps[k] = ps[pivotindex];
6092 pivot = lu[ps[k]][k];
6093 for (i = k + 1; i < n + N; i++) {
6094 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
6096 for (j = k + 1; j < n + N; j++)
6097 lu[ps[i]][j] -= mult * lu[ps[k]][j];
6103 return lu[ps[n + N - 1]][n + N - 1] != 0.0;
6121 void tetgenmesh::lu_solve(REAL lu[4][4],
int n,
int* ps, REAL* b,
int N)
6126 for (i = N; i < n + N; i++) X[i] = 0.0;
6129 for (i = N; i < n + N; i++) {
6131 for (j = N; j < i + N; j++)
6132 dot += lu[ps[i]][j] * X[j];
6133 X[i] = b[ps[i]] - dot;
6137 for (i = n + N - 1; i >= N; i--) {
6139 for (j = i + 1; j < n + N; j++)
6140 dot += lu[ps[i]][j] * X[j];
6141 X[i] = (X[i] - dot) / lu[ps[i]][i];
6144 for (i = N; i < n + N; i++) b[i] = X[i];
6159 REAL tetgenmesh::incircle3d(point pa, point pb, point pc, point pd)
6161 REAL area2[2], n1[3], n2[3], c[3];
6165 facenormal(pa, pb, pc, n1, 1, NULL);
6166 area2[0] = dot(n1, n1);
6167 facenormal(pb, pa, pd, n2, 1, NULL);
6168 area2[1] = dot(n2, n2);
6170 if (area2[0] > area2[1]) {
6172 circumsphere(pa, pb, pc, NULL, c, &r);
6173 d = distance(c, pd);
6177 circumsphere(pb, pa, pd, NULL, c, &r);
6178 d = distance(c, pc);
6186 if (fabs(sign) / r < b->epsilon) {
6210 void tetgenmesh::facenormal(point pa, point pb, point pc, REAL *n,
int pivot,
6213 REAL v1[3], v2[3], v3[3], *pv1, *pv2;
6216 v1[0] = pb[0] - pa[0];
6217 v1[1] = pb[1] - pa[1];
6218 v1[2] = pb[2] - pa[2];
6219 v2[0] = pa[0] - pc[0];
6220 v2[1] = pa[1] - pc[1];
6221 v2[2] = pa[2] - pc[2];
6226 v3[0] = pc[0] - pb[0];
6227 v3[1] = pc[1] - pb[1];
6228 v3[2] = pc[2] - pb[2];
6248 *lav = (sqrt(L1) + sqrt(L2) + sqrt(L3)) / 3.0;
6276 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
6281 v1[0] = e2[0] - e1[0];
6282 v1[1] = e2[1] - e1[1];
6283 v1[2] = e2[2] - e1[2];
6284 v2[0] = p[0] - e1[0];
6285 v2[1] = p[1] - e1[1];
6286 v2[2] = p[2] - e1[2];
6288 len = sqrt(dot(v1, v1));
6295 return sqrt(dot(v2, v2) - l_p * l_p);
6304 REAL tetgenmesh::triarea(REAL* pa, REAL* pb, REAL* pc)
6309 A[0][0] = pb[0] - pa[0];
6310 A[0][1] = pb[1] - pa[1];
6311 A[0][2] = pb[2] - pa[2];
6312 A[1][0] = pc[0] - pa[0];
6313 A[1][1] = pc[1] - pa[1];
6314 A[1][2] = pc[2] - pa[2];
6316 cross(A[0], A[1], A[2]);
6318 return 0.5 * sqrt(dot(A[2], A[2]));
6321 REAL tetgenmesh::orient3dfast(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
6327 adx = pa[0] - pd[0];
6328 bdx = pb[0] - pd[0];
6329 cdx = pc[0] - pd[0];
6330 ady = pa[1] - pd[1];
6331 bdy = pb[1] - pd[1];
6332 cdy = pc[1] - pd[1];
6333 adz = pa[2] - pd[2];
6334 bdz = pb[2] - pd[2];
6335 cdz = pc[2] - pd[2];
6337 return adx * (bdy * cdz - bdz * cdy)
6338 + bdx * (cdy * adz - cdz * ady)
6339 + cdx * (ady * bdz - adz * bdy);
6355 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
6357 REAL v1[3], v2[3], np[3];
6358 REAL theta, costheta, lenlen;
6359 REAL ori, len1, len2;
6362 v1[0] = p1[0] - o[0];
6363 v1[1] = p1[1] - o[1];
6364 v1[2] = p1[2] - o[2];
6365 v2[0] = p2[0] - o[0];
6366 v2[1] = p2[1] - o[1];
6367 v2[2] = p2[2] - o[2];
6368 len1 = sqrt(dot(v1, v1));
6369 len2 = sqrt(dot(v2, v2));
6370 lenlen = len1 * len2;
6372 costheta = dot(v1, v2) / lenlen;
6373 if (costheta > 1.0) {
6375 }
else if (costheta < -1.0) {
6378 theta = acos(costheta);
6381 np[0] = o[0] + n[0];
6382 np[1] = o[1] + n[1];
6383 np[2] = o[2] + n[2];
6385 ori = orient3d(p1, o, np, p2);
6387 theta = 2 * PI - theta;
6400 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
6405 v1[0] = e2[0] - e1[0];
6406 v1[1] = e2[1] - e1[1];
6407 v1[2] = e2[2] - e1[2];
6408 v2[0] = p[0] - e1[0];
6409 v2[1] = p[1] - e1[1];
6410 v2[2] = p[2] - e1[2];
6412 len = sqrt(dot(v1, v1));
6418 prj[0] = e1[0] + l_p * v1[0];
6419 prj[1] = e1[1] + l_p * v1[1];
6420 prj[2] = e1[2] + l_p * v1[2];
6429 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
6431 REAL fnormal[3], v1[3];
6435 facenormal(f1, f2, f3, fnormal, 1, NULL);
6436 len = sqrt(fnormal[0]*fnormal[0] + fnormal[1]*fnormal[1] +
6437 fnormal[2]*fnormal[2]);
6442 v1[0] = p[0] - f1[0];
6443 v1[1] = p[1] - f1[1];
6444 v1[2] = p[2] - f1[2];
6446 dist = dot(fnormal, v1);
6449 prj[0] = p[0] - dist * fnormal[0];
6450 prj[1] = p[1] - dist * fnormal[1];
6451 prj[2] = p[2] - dist * fnormal[2];
6465 bool tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
6466 REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
6468 REAL N[4][3], vol, cosd, len;
6469 int f1 = 0, f2 = 0, i, j;
6474 tetallnormal(pa, pb, pc, pd, N, &vol);
6478 for (i = 0; i < 4; i++) {
6479 len = sqrt(dot(N[i], N[i]));
6481 for (j = 0; j < 3; j++) N[i][j] /= len;
6491 facenormal(pc, pb, pd, N[0], 1, NULL);
6492 facenormal(pa, pc, pd, N[1], 1, NULL);
6493 facenormal(pb, pa, pd, N[2], 1, NULL);
6494 facenormal(pa, pb, pc, N[3], 1, NULL);
6496 for (i = 0; i < 4; i++) {
6497 len = sqrt(dot(N[i], N[i]));
6499 for (j = 0; j < 3; j++) N[i][j] /= len;
6509 if (cosdd != NULL) {
6510 for (i = 0; i < 6; i++) {
6515 if (cosmaxd != NULL) {
6518 if (cosmind != NULL) {
6526 for (i = 0; i < 6; i++) {
6528 case 0: f1 = 0; f2 = 1;
break;
6529 case 1: f1 = 1; f2 = 2;
break;
6530 case 2: f1 = 2; f2 = 3;
break;
6531 case 3: f1 = 0; f2 = 3;
break;
6532 case 4: f1 = 2; f2 = 0;
break;
6533 case 5: f1 = 1; f2 = 3;
break;
6535 cosd = -dot(N[f1], N[f2]);
6536 if (cosd < -1.0) cosd = -1.0;
6537 if (cosd > 1.0) cosd = 1.0;
6538 if (cosdd) cosdd[i] = cosd;
6539 if (cosmaxd || cosmind) {
6541 if (cosmaxd) *cosmaxd = cosd;
6542 if (cosmind) *cosmind = cosd;
6544 if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
6545 if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
6563 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
6564 REAL N[4][3], REAL* volume)
6566 REAL A[4][4], rhs[4], D;
6571 for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];
6572 for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];
6573 for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];
6576 if (lu_decmp(A, 3, indx, &D, 0)) {
6577 if (volume != NULL) {
6579 *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
6581 for (j = 0; j < 3; j++) {
6582 for (i = 0; i < 3; i++) rhs[i] = 0.0;
6584 lu_solve(A, 3, indx, rhs, 0);
6585 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
6588 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
6591 if (volume != NULL) {
6606 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
6608 REAL V[6][3], edgelength[6], longlen;
6609 REAL vda[3], vdb[3], vdc[3];
6610 REAL N[4][3], A[4][4], rhs[4], D;
6611 REAL H[4], volume, minheightinv;
6616 for (i = 0; i < 3; i++) V[0][i] = pa[i] - pd[i];
6617 for (i = 0; i < 3; i++) V[1][i] = pb[i] - pd[i];
6618 for (i = 0; i < 3; i++) V[2][i] = pc[i] - pd[i];
6619 for (i = 0; i < 3; i++) V[3][i] = pb[i] - pa[i];
6620 for (i = 0; i < 3; i++) V[4][i] = pc[i] - pb[i];
6621 for (i = 0; i < 3; i++) V[5][i] = pa[i] - pc[i];
6624 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
6627 longlen = edgelength[0];
6628 for (i = 1; i < 6; i++) {
6629 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
6633 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
6634 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
6635 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
6637 lu_decmp(A, 3, indx, &D, 0);
6639 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
6641 if (volume == 0.0)
return 1.0e+200;
6644 for (j = 0; j < 3; j++) {
6645 for (i = 0; i < 3; i++) rhs[i] = 0.0;
6647 lu_solve(A, 3, indx, rhs, 0);
6648 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
6651 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
6653 for (i = 0; i < 4; i++) {
6655 H[i] = sqrt(dot(N[i], N[i]));
6663 minheightinv = H[0];
6664 for (i = 1; i < 4; i++) {
6665 if (H[i] > minheightinv) minheightinv = H[i];
6668 return sqrt(longlen) * minheightinv;
6686 bool tetgenmesh::circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
6687 REAL* cent, REAL* radius)
6689 REAL A[4][4], rhs[4], D;
6693 A[0][0] = pb[0] - pa[0];
6694 A[0][1] = pb[1] - pa[1];
6695 A[0][2] = pb[2] - pa[2];
6696 A[1][0] = pc[0] - pa[0];
6697 A[1][1] = pc[1] - pa[1];
6698 A[1][2] = pc[2] - pa[2];
6700 A[2][0] = pd[0] - pa[0];
6701 A[2][1] = pd[1] - pa[1];
6702 A[2][2] = pd[2] - pa[2];
6704 cross(A[0], A[1], A[2]);
6708 rhs[0] = 0.5 * dot(A[0], A[0]);
6709 rhs[1] = 0.5 * dot(A[1], A[1]);
6711 rhs[2] = 0.5 * dot(A[2], A[2]);
6718 if (!lu_decmp(A, 3, indx, &D, 0)) {
6719 if (radius != (REAL *) NULL) *radius = 0.0;
6722 lu_solve(A, 3, indx, rhs, 0);
6723 if (cent != (REAL *) NULL) {
6724 cent[0] = pa[0] + rhs[0];
6725 cent[1] = pa[1] + rhs[1];
6726 cent[2] = pa[2] + rhs[2];
6728 if (radius != (REAL *) NULL) {
6729 *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
6744 bool tetgenmesh::orthosphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
6745 REAL aheight, REAL bheight, REAL cheight,
6746 REAL dheight, REAL* orthocent, REAL* radius)
6748 REAL A[4][4], rhs[4], D;
6752 A[0][0] = 1.0; A[0][1] = pa[0]; A[0][2] = pa[1]; A[0][3] = pa[2];
6753 A[1][0] = 1.0; A[1][1] = pb[0]; A[1][2] = pb[1]; A[1][3] = pb[2];
6754 A[2][0] = 1.0; A[2][1] = pc[0]; A[2][2] = pc[1]; A[2][3] = pc[2];
6755 A[3][0] = 1.0; A[3][1] = pd[0]; A[3][2] = pd[1]; A[3][3] = pd[2];
6758 rhs[0] = 0.5 * aheight;
6759 rhs[1] = 0.5 * bheight;
6760 rhs[2] = 0.5 * cheight;
6761 rhs[3] = 0.5 * dheight;
6765 if (!lu_decmp(A, 4, indx, &D, 0)) {
6766 if (radius != (REAL *) NULL) *radius = 0.0;
6769 lu_solve(A, 4, indx, rhs, 0);
6771 if (orthocent != (REAL *) NULL) {
6772 orthocent[0] = rhs[1];
6773 orthocent[1] = rhs[2];
6774 orthocent[2] = rhs[3];
6776 if (radius != (REAL *) NULL) {
6782 *radius = sqrt(rhs[1] * rhs[1] + rhs[2] * rhs[2] + rhs[3] * rhs[3]
6788 void tetgenmesh::tetcircumcenter(point tetorg, point tetdest, point tetfapex,
6789 point tettapex, REAL *circumcenter, REAL *radius)
6791 REAL xot, yot, zot, xdt, ydt, zdt, xft, yft, zft;
6792 REAL otlength, dtlength, ftlength;
6793 REAL xcrossdf, ycrossdf, zcrossdf;
6794 REAL xcrossfo, ycrossfo, zcrossfo;
6795 REAL xcrossod, ycrossod, zcrossod;
6802 xot = tetorg[0] - tettapex[0];
6803 yot = tetorg[1] - tettapex[1];
6804 zot = tetorg[2] - tettapex[2];
6805 xdt = tetdest[0] - tettapex[0];
6806 ydt = tetdest[1] - tettapex[1];
6807 zdt = tetdest[2] - tettapex[2];
6808 xft = tetfapex[0] - tettapex[0];
6809 yft = tetfapex[1] - tettapex[1];
6810 zft = tetfapex[2] - tettapex[2];
6812 otlength = xot * xot + yot * yot + zot * zot;
6813 dtlength = xdt * xdt + ydt * ydt + zdt * zdt;
6814 ftlength = xft * xft + yft * yft + zft * zft;
6816 xcrossdf = ydt * zft - yft * zdt;
6817 ycrossdf = zdt * xft - zft * xdt;
6818 zcrossdf = xdt * yft - xft * ydt;
6819 xcrossfo = yft * zot - yot * zft;
6820 ycrossfo = zft * xot - zot * xft;
6821 zcrossfo = xft * yot - xot * yft;
6822 xcrossod = yot * zdt - ydt * zot;
6823 ycrossod = zot * xdt - zdt * xot;
6824 zcrossod = xot * ydt - xdt * yot;
6833 denominator = 0.5 / orient3d(tetorg, tetdest, tetfapex, tettapex);
6839 xct = (otlength * xcrossdf + dtlength * xcrossfo + ftlength * xcrossod) *
6841 yct = (otlength * ycrossdf + dtlength * ycrossfo + ftlength * ycrossod) *
6843 zct = (otlength * zcrossdf + dtlength * zcrossfo + ftlength * zcrossod) *
6846 circumcenter[0] = xct + tettapex[0];
6847 circumcenter[1] = yct + tettapex[1];
6848 circumcenter[2] = zct + tettapex[2];
6850 if (radius != NULL) {
6851 *radius = sqrt(xct * xct + yct * yct + zct * zct);
6878 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
6881 REAL n[3], det, det1;
6884 facenormal(pa, pb, pc, n, 1, NULL);
6886 det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
6887 + n[2] * (e2[2] - e1[2]);
6890 det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
6891 + n[2] * (pa[2] - e1[2]);
6893 ip[0] = e1[0] + *u * (e2[0] - e1[0]);
6894 ip[1] = e1[1] + *u * (e2[1] - e1[1]);
6895 ip[2] = e1[2] + *u * (e2[2] - e1[2]);
6913 int tetgenmesh::linelineint(REAL* A, REAL* B, REAL* C, REAL* D, REAL* P,
6914 REAL* Q, REAL* tp, REAL* tq)
6916 REAL vab[3], vcd[3], vca[3];
6917 REAL vab_vab, vcd_vcd, vab_vcd;
6918 REAL vca_vab, vca_vcd;
6922 for (i = 0; i < 3; i++) {
6923 vab[i] = B[i] - A[i];
6924 vcd[i] = D[i] - C[i];
6925 vca[i] = A[i] - C[i];
6928 vab_vab = dot(vab, vab);
6929 vcd_vcd = dot(vcd, vcd);
6930 vab_vcd = dot(vab, vcd);
6932 det = vab_vab * vcd_vcd - vab_vcd * vab_vcd;
6934 eps = det / (fabs(vab_vab * vcd_vcd) + fabs(vab_vcd * vab_vcd));
6935 if (eps < b->epsilon) {
6939 vca_vab = dot(vca, vab);
6940 vca_vcd = dot(vca, vcd);
6942 *tp = (vcd_vcd * (- vca_vab) + vab_vcd * vca_vcd) / det;
6943 *tq = (vab_vcd * (- vca_vab) + vab_vab * vca_vcd) / det;
6945 for (i = 0; i < 3; i++) P[i] = A[i] + (*tp) * vab[i];
6946 for (i = 0; i < 3; i++) Q[i] = C[i] + (*tq) * vcd[i];
6972 REAL tetgenmesh::tetprismvol(REAL* p0, REAL* p1, REAL* p2, REAL* p3)
6974 REAL *p4, *p5, *p6, *p7;
6975 REAL w4, w5, w6, w7;
6990 vol[0] = orient4d(p5, p6, p4, p3, p7, w5, w6, w4, 0, w7);
6991 vol[1] = orient4d(p3, p6, p2, p0, p1, 0, w6, 0, 0, 0);
6992 vol[2] = orient4d(p4, p6, p3, p0, p1, w4, w6, 0, 0, 0);
6993 vol[3] = orient4d(p6, p5, p4, p3, p1, w6, w5, w4, 0, 0);
6995 return fabs(vol[0]) + fabs(vol[1]) + fabs(vol[2]) + fabs(vol[3]);
7004 bool tetgenmesh::calculateabovepoint(arraypool *facpoints, point *ppa,
7005 point *ppb, point *ppc)
7007 point *ppt, pa, pb, pc;
7008 REAL v1[3], v2[3], n[3];
7009 REAL lab, len, A, area;
7013 ppt = (point *) fastlookup(facpoints, 0);
7019 for (i = 1; i < facpoints->objects; i++) {
7020 ppt = (point *) fastlookup(facpoints, i);
7021 x = (*ppt)[0] - pa[0];
7022 y = (*ppt)[1] - pa[1];
7023 z = (*ppt)[2] - pa[2];
7024 len = x * x + y * y + z * z;
7033 printf(
"Warning: All points of a facet are coincident with %d.\n",
7040 v1[0] = pb[0] - pa[0];
7041 v1[1] = pb[1] - pa[1];
7042 v1[2] = pb[2] - pa[2];
7044 for (i = 1; i < facpoints->objects; i++) {
7045 ppt = (point *) fastlookup(facpoints, i);
7046 v2[0] = (*ppt)[0] - pa[0];
7047 v2[1] = (*ppt)[1] - pa[1];
7048 v2[2] = (*ppt)[2] - pa[2];
7059 printf(
"Warning: All points of a facet are collinaer with [%d, %d].\n",
7060 pointmark(pa), pointmark(pb));
7066 facenormal(pa, pb, pc, n, 1, NULL);
7067 len = sqrt(dot(n, n));
7072 dummypoint[0] = pa[0] + lab * n[0];
7073 dummypoint[1] = pa[1] + lab * n[1];
7074 dummypoint[2] = pa[2] + lab * n[2];
7094 void tetgenmesh::calculateabovepoint4(point pa, point pb, point pc, point pd)
7096 REAL n1[3], n2[3], *norm;
7097 REAL len, len1, len2;
7100 facenormal(pa, pb, pc, n1, 1, NULL);
7101 len1 = sqrt(dot(n1, n1));
7102 facenormal(pa, pb, pd, n2, 1, NULL);
7103 len2 = sqrt(dot(n2, n2));
7114 len = distance(pa, pb);
7115 dummypoint[0] = pa[0] + len * norm[0];
7116 dummypoint[1] = pa[1] + len * norm[1];
7117 dummypoint[2] = pa[2] + len * norm[2];
7130 void tetgenmesh::report_overlapping_facets(face *f1, face *f2, REAL dihedang)
7132 point pa, pb, pc, pd;
7140 printf(
"Found two %s self-intersecting facets.\n",
7141 dihedang > 0 ?
"nearly" :
"exactly");
7142 printf(
" 1st: [%d, %d, %d] #%d\n",
7143 pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1));
7144 printf(
" 2nd: [%d, %d, %d] #%d\n",
7145 pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2));
7147 printf(
"The dihedral angle between them is %g degree.\n",
7148 dihedang / PI * 180.0);
7149 printf(
"Hint: You may use -p/# to decrease the dihedral angle");
7150 printf(
" tolerance %g (degree).\n", b->facet_overlap_ang_tol);
7153 if (shellmark(*f1) != shellmark(*f2)) {
7155 printf(
"Found two overlapping facets.\n");
7157 printf(
"Found two duplicated facets.\n");
7159 printf(
" 1st: [%d, %d, %d] #%d\n",
7160 pointmark(pa), pointmark(pb), pointmark(pc), shellmark(*f1));
7161 printf(
" 2nd: [%d, %d, %d] #%d\n",
7162 pointmark(pa), pointmark(pb), pointmark(pd), shellmark(*f2));
7167 sevent.f_marker1 = shellmark(*f1);
7168 sevent.f_vertices1[0] = pointmark(pa);
7169 sevent.f_vertices1[1] = pointmark(pb);
7170 sevent.f_vertices1[2] = pointmark(pc);
7171 sevent.f_marker2 = shellmark(*f2);
7172 sevent.f_vertices2[0] = pointmark(pa);
7173 sevent.f_vertices2[1] = pointmark(pb);
7174 sevent.f_vertices2[2] = pointmark(pd);
7176 terminatetetgen(
this, 3);
7195 int tetgenmesh::report_selfint_edge(point e1, point e2, face *iedge,
7196 triface* itet,
enum interresult dir)
7198 point forg = NULL, fdest = NULL, fapex = NULL;
7199 int etype = 0, geomtag = 0, facemark = 0;
7201 if (iedge != NULL) {
7202 if (iedge->sh[5] != NULL) {
7206 fapex = sapex(*iedge);
7207 facemark = shellmark(*iedge);
7210 forg = farsorg(*iedge);
7211 fdest = farsdest(*iedge);
7214 spivot(*iedge, parentsh);
7215 if (parentsh.sh != NULL) {
7216 facemark = shellmark(parentsh);
7219 geomtag = shellmark(*iedge);
7222 if (dir == SHAREEDGE) {
7225 tsspivot1(*itet, colseg);
7227 if (colseg.sh != iedge->sh) {
7229 spivot(colseg, parentsh);
7230 printf(
"PLC Error: Two segments are overlapping.\n");
7231 printf(
" Segment 1: [%d, %d] #%d (%d)\n", pointmark(sorg(colseg)),
7232 pointmark(sdest(colseg)), shellmark(colseg),
7233 parentsh.sh ? shellmark(parentsh) : 0);
7234 printf(
" Segment 2: [%d, %d] #%d (%d)\n", pointmark(forg),
7235 pointmark(fdest), geomtag, facemark);
7237 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7238 sevent.s_marker1 = shellmark(colseg);
7239 sevent.f_vertices1[0] = pointmark( sorg(colseg));
7240 sevent.f_vertices1[1] = pointmark(sdest(colseg));
7241 sevent.f_vertices1[2] = 0;
7242 sevent.f_marker2 = facemark;
7243 sevent.s_marker2 = geomtag;
7244 sevent.f_vertices2[0] = pointmark(forg);
7245 sevent.f_vertices2[1] = pointmark(fdest);
7246 sevent.f_vertices2[2] = 0;
7249 terminatetetgen(
this, 2);
7251 }
else if (etype == 2) {
7252 printf(
"PLC Error: A segment lies in a facet.\n");
7253 printf(
" Segment: [%d, %d] #%d\n", pointmark(sorg(colseg)),
7254 pointmark(sdest(colseg)), shellmark(colseg));
7255 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg),
7256 pointmark(fdest), pointmark(fapex), geomtag);
7258 sevent.f_marker1 = 0;
7259 sevent.s_marker1 = shellmark(colseg);
7260 sevent.f_vertices1[0] = pointmark( sorg(colseg));
7261 sevent.f_vertices1[1] = pointmark(sdest(colseg));
7262 sevent.f_vertices1[2] = 0;
7263 sevent.f_marker2 = geomtag;
7264 sevent.s_marker2 = 0;
7265 sevent.f_vertices2[0] = pointmark(forg);
7266 sevent.f_vertices2[1] = pointmark(fdest);
7267 sevent.f_vertices2[2] = pointmark(fapex);
7269 }
else if (dir == SHAREFACE) {
7272 tspivot(*itet, colface);
7274 if (colface.sh != iedge->sh) {
7275 printf(
"PLC Error: Two facets are overlapping.\n");
7276 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(forg),
7277 pointmark(fdest), pointmark(fapex), geomtag);
7278 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(sorg(colface)),
7279 pointmark(sdest(colface)), pointmark(sapex(colface)),
7280 shellmark(colface));
7282 sevent.f_marker1 = geomtag;
7283 sevent.s_marker1 = 0;
7284 sevent.f_vertices1[0] = pointmark(forg);
7285 sevent.f_vertices1[1] = pointmark(fdest);
7286 sevent.f_vertices1[2] = pointmark(fapex);
7287 sevent.f_marker2 = shellmark(colface);
7288 sevent.s_marker2 = 0;
7289 sevent.f_vertices2[0] = pointmark(sorg(colface));
7290 sevent.f_vertices2[1] = pointmark(sdest(colface));
7291 sevent.f_vertices2[2] = pointmark(sapex(colface));
7294 terminatetetgen(
this, 2);
7297 terminatetetgen(
this, 2);
7299 }
else if (dir == ACROSSVERT) {
7300 point pp = dest(*itet);
7301 if ((pointtype(pp) == RIDGEVERTEX) || (pointtype(pp) == FACETVERTEX)
7302 || (pointtype(pp) == VOLVERTEX)) {
7304 printf(
"PLC Error: A vertex lies in a segment.\n");
7305 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
7306 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(forg),
7307 pointmark(fdest), geomtag, facemark);
7309 sevent.f_marker1 = 0;
7310 sevent.s_marker1 = 0;
7311 sevent.f_vertices1[0] = pointmark(pp);
7312 sevent.f_vertices1[1] = 0;
7313 sevent.f_vertices1[2] = 0;
7314 sevent.f_marker2 = facemark;
7315 sevent.s_marker2 = geomtag;
7316 sevent.f_vertices2[0] = pointmark(forg);
7317 sevent.f_vertices2[1] = pointmark(fdest);
7318 sevent.f_vertices2[2] = 0;
7319 sevent.int_point[0] = pp[0];
7320 sevent.int_point[1] = pp[1];
7321 sevent.int_point[2] = pp[2];
7322 }
else if (etype == 2) {
7323 printf(
"PLC Error: A vertex lies in a facet.\n");
7324 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
7325 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg), pointmark(fdest),
7326 pointmark(fapex), geomtag);
7328 sevent.f_marker1 = 0;
7329 sevent.s_marker1 = 0;
7330 sevent.f_vertices1[0] = pointmark(pp);
7331 sevent.f_vertices1[1] = 0;
7332 sevent.f_vertices1[2] = 0;
7333 sevent.f_marker2 = geomtag;
7334 sevent.s_marker2 = 0;
7335 sevent.f_vertices2[0] = pointmark(forg);
7336 sevent.f_vertices2[1] = pointmark(fdest);
7337 sevent.f_vertices2[2] = pointmark(fapex);
7338 sevent.int_point[0] = pp[0];
7339 sevent.int_point[1] = pp[1];
7340 sevent.int_point[2] = pp[2];
7342 }
else if (pointtype(pp) == FREESEGVERTEX) {
7343 face parentseg, parentsh;
7344 sdecode(point2sh(pp), parentseg);
7345 spivot(parentseg, parentsh);
7346 if (parentseg.sh != NULL) {
7347 point p1 = farsorg(parentseg);
7348 point p2 = farsdest(parentseg);
7350 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g).\n",
7351 pp[0], pp[1], pp[2]);
7352 printf(
" Segment 1: [%d, %d], #%d (%d)\n", pointmark(forg),
7353 pointmark(fdest), geomtag, facemark);
7354 printf(
" Segment 2: [%d, %d], #%d (%d)\n", pointmark(p1),
7355 pointmark(p2), shellmark(parentseg),
7356 parentsh.sh ? shellmark(parentsh) : 0);
7358 sevent.f_marker1 = facemark;
7359 sevent.s_marker1 = geomtag;
7360 sevent.f_vertices1[0] = pointmark(forg);
7361 sevent.f_vertices1[1] = pointmark(fdest);
7362 sevent.f_vertices1[2] = 0;
7363 sevent.f_marker2 = (parentsh.sh ? shellmark(parentsh) : 0);
7364 sevent.s_marker2 = shellmark(parentseg);
7365 sevent.f_vertices2[0] = pointmark(p1);
7366 sevent.f_vertices2[1] = pointmark(p2);
7367 sevent.f_vertices2[2] = 0;
7368 sevent.int_point[0] = pp[0];
7369 sevent.int_point[1] = pp[1];
7370 sevent.int_point[2] = pp[2];
7371 }
else if (etype == 2) {
7372 printf(
"PLC Error: A segment and a facet intersect at point");
7373 printf(
" (%g,%g,%g).\n", pp[0], pp[1], pp[2]);
7374 printf(
" Segment: [%d, %d], #%d (%d)\n", pointmark(p1),
7375 pointmark(p2), shellmark(parentseg),
7376 parentsh.sh ? shellmark(parentsh) : 0);
7377 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(forg),
7378 pointmark(fdest), pointmark(fapex), geomtag);
7380 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7381 sevent.s_marker1 = shellmark(parentseg);
7382 sevent.f_vertices1[0] = pointmark(p1);
7383 sevent.f_vertices1[1] = pointmark(p2);
7384 sevent.f_vertices1[2] = 0;
7385 sevent.f_marker2 = geomtag;
7386 sevent.s_marker2 = 0;
7387 sevent.f_vertices2[0] = pointmark(forg);
7388 sevent.f_vertices2[1] = pointmark(fdest);
7389 sevent.f_vertices2[2] = pointmark(fapex);
7390 sevent.int_point[0] = pp[0];
7391 sevent.int_point[1] = pp[1];
7392 sevent.int_point[2] = pp[2];
7395 terminatetetgen(
this, 2);
7397 }
else if (pointtype(pp) == FREEFACETVERTEX) {
7399 sdecode(point2sh(pp), parentsh);
7400 if (parentsh.sh != NULL) {
7401 point p1 = sorg(parentsh);
7402 point p2 = sdest(parentsh);
7403 point p3 = sapex(parentsh);
7405 printf(
"PLC Error: A segment and a facet intersect at point");
7406 printf(
" (%g,%g,%g).\n", pp[0], pp[1], pp[2]);
7407 printf(
" Segment : [%d, %d], #%d (%d)\n", pointmark(forg),
7408 pointmark(fdest), geomtag, facemark);
7409 printf(
" Facet : [%d, %d, %d] #%d.\n", pointmark(p1),
7410 pointmark(p2), pointmark(p3), shellmark(parentsh));
7412 sevent.f_marker1 = facemark;
7413 sevent.s_marker1 = geomtag;
7414 sevent.f_vertices1[0] = pointmark(forg);
7415 sevent.f_vertices1[1] = pointmark(fdest);
7416 sevent.f_vertices1[2] = 0;
7417 sevent.f_marker2 = shellmark(parentsh);
7418 sevent.s_marker2 = 0;
7419 sevent.f_vertices2[0] = pointmark(p1);
7420 sevent.f_vertices2[1] = pointmark(p2);
7421 sevent.f_vertices2[2] = pointmark(p3);
7422 sevent.int_point[0] = pp[0];
7423 sevent.int_point[1] = pp[1];
7424 sevent.int_point[2] = pp[2];
7425 }
else if (etype == 2) {
7426 printf(
"PLC Error: Two facets intersect at point (%g,%g,%g).\n",
7427 pp[0], pp[1], pp[2]);
7428 printf(
" Facet 1: [%d, %d, %d] #%d.\n", pointmark(forg),
7429 pointmark(fdest), pointmark(fapex), geomtag);
7430 printf(
" Facet 2: [%d, %d, %d] #%d.\n", pointmark(p1),
7431 pointmark(p2), pointmark(p3), shellmark(parentsh));
7433 sevent.f_marker1 = geomtag;
7434 sevent.s_marker1 = 0;
7435 sevent.f_vertices1[0] = pointmark(forg);
7436 sevent.f_vertices1[1] = pointmark(fdest);
7437 sevent.f_vertices1[2] = pointmark(fapex);
7438 sevent.f_marker2 = shellmark(parentsh);
7439 sevent.s_marker2 = 0;
7440 sevent.f_vertices2[0] = pointmark(p1);
7441 sevent.f_vertices2[1] = pointmark(p2);
7442 sevent.f_vertices2[2] = pointmark(p3);
7443 sevent.int_point[0] = pp[0];
7444 sevent.int_point[1] = pp[1];
7445 sevent.int_point[2] = pp[2];
7448 terminatetetgen(
this, 2);
7450 }
else if (pointtype(pp) == FREEVOLVERTEX) {
7454 terminatetetgen(
this, 2);
7456 terminatetetgen(
this, 2);
7458 terminatetetgen(
this, 3);
7459 }
else if (dir == ACROSSEDGE) {
7460 if (issubseg(*itet)) {
7462 tsspivot1(*itet, checkseg);
7464 spivot(checkseg, parentsh);
7466 point p1 = sorg(checkseg);
7467 point p2 = sdest(checkseg);
7468 REAL P[3], Q[3], tp = 0, tq = 0;
7469 linelineint(e1, e2, p1, p2, P, Q, &tp, &tq);
7471 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g).\n",
7473 printf(
" Segment 1: [%d, %d] #%d (%d)\n", pointmark(forg),
7474 pointmark(fdest), geomtag, facemark);
7475 printf(
" Segment 2: [%d, %d] #%d (%d)\n", pointmark(p1),
7476 pointmark(p2), shellmark(checkseg),
7477 parentsh.sh ? shellmark(parentsh) : 0);
7479 sevent.f_marker1 = facemark;
7480 sevent.s_marker1 = geomtag;
7481 sevent.f_vertices1[0] = pointmark(forg);
7482 sevent.f_vertices1[1] = pointmark(fdest);
7483 sevent.f_vertices1[2] = 0;
7484 sevent.f_marker2 = (parentsh.sh ? shellmark(parentsh) : 0);
7485 sevent.s_marker2 = shellmark(checkseg);
7486 sevent.f_vertices2[0] = pointmark(p1);
7487 sevent.f_vertices2[1] = pointmark(p2);
7488 sevent.f_vertices2[2] = 0;
7489 sevent.int_point[0] = P[0];
7490 sevent.int_point[1] = P[1];
7491 sevent.int_point[2] = P[2];
7492 }
else if (etype == 2) {
7493 printf(
"PLC Error: A segment and a facet intersect at point");
7494 printf(
" (%g,%g,%g).\n", P[0], P[1], P[2]);
7495 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(p1),
7496 pointmark(p2), shellmark(checkseg),
7497 parentsh.sh ? shellmark(parentsh) : 0);
7498 printf(
" Facet: [%d, %d, %d] #%d.\n", pointmark(forg),
7499 pointmark(fdest), pointmark(fapex), geomtag);
7501 sevent.f_marker1 = (parentsh.sh ? shellmark(parentsh) : 0);
7502 sevent.s_marker1 = shellmark(checkseg);
7503 sevent.f_vertices1[0] = pointmark(p1);
7504 sevent.f_vertices1[1] = pointmark(p2);
7505 sevent.f_vertices1[2] = 0;
7506 sevent.f_marker2 = geomtag;
7507 sevent.s_marker2 = 0;
7508 sevent.f_vertices2[0] = pointmark(forg);
7509 sevent.f_vertices2[1] = pointmark(fdest);
7510 sevent.f_vertices2[2] = pointmark(fapex);
7511 sevent.int_point[0] = P[0];
7512 sevent.int_point[1] = P[1];
7513 sevent.int_point[2] = P[2];
7515 terminatetetgen(
this, 3);
7517 }
else if (dir == ACROSSFACE) {
7518 if (issubface(*itet)) {
7520 tspivot(*itet, checksh);
7521 point p1 = sorg(checksh);
7522 point p2 = sdest(checksh);
7523 point p3 = sapex(checksh);
7525 planelineint(p1, p2, p3, e1, e2, ip, &u);
7527 printf(
"PLC Error: A segment and a facet intersect at point");
7528 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7529 printf(
" Segment: [%d, %d] #%d (%d)\n", pointmark(forg),
7530 pointmark(fdest), geomtag, facemark);
7531 printf(
" Facet: [%d, %d, %d] #%d.\n", pointmark(p1),
7532 pointmark(p2), pointmark(p3), shellmark(checksh));
7534 sevent.f_marker1 = facemark;
7535 sevent.s_marker1 = geomtag;
7536 sevent.f_vertices1[0] = pointmark(forg);
7537 sevent.f_vertices1[1] = pointmark(fdest);
7538 sevent.f_vertices1[2] = 0;
7539 sevent.f_marker2 = shellmark(checksh);
7540 sevent.s_marker2 = 0;
7541 sevent.f_vertices2[0] = pointmark(p1);
7542 sevent.f_vertices2[1] = pointmark(p2);
7543 sevent.f_vertices2[2] = pointmark(p3);
7544 sevent.int_point[0] = ip[0];
7545 sevent.int_point[1] = ip[1];
7546 sevent.int_point[2] = ip[2];
7547 }
else if (etype == 2) {
7548 printf(
"PLC Error: Two facets intersect at point (%g,%g,%g).\n",
7549 ip[0], ip[1], ip[2]);
7550 printf(
" Facet 1: [%d, %d, %d] #%d.\n", pointmark(forg),
7551 pointmark(fdest), pointmark(fapex), geomtag);
7552 printf(
" Facet 2: [%d, %d, %d] #%d.\n", pointmark(p1),
7553 pointmark(p2), pointmark(p3), shellmark(checksh));
7555 sevent.f_marker1 = geomtag;
7556 sevent.s_marker1 = 0;
7557 sevent.f_vertices1[0] = pointmark(forg);
7558 sevent.f_vertices1[1] = pointmark(fdest);
7559 sevent.f_vertices1[2] = pointmark(fapex);
7560 sevent.f_marker2 = shellmark(checksh);
7561 sevent.s_marker2 = 0;
7562 sevent.f_vertices2[0] = pointmark(p1);
7563 sevent.f_vertices2[1] = pointmark(p2);
7564 sevent.f_vertices2[2] = pointmark(p3);
7565 sevent.int_point[0] = ip[0];
7566 sevent.int_point[1] = ip[1];
7567 sevent.int_point[2] = ip[2];
7569 terminatetetgen(
this, 3);
7573 terminatetetgen(
this, 2);
7592 int tetgenmesh::report_selfint_face(point p1, point p2, point p3, face* sface,
7593 triface* iedge,
int intflag,
int* types,
int* poss)
7596 point e1 = NULL, e2 = NULL, e3 = NULL;
7597 int etype = 0, geomtag = 0, facemark = 0;
7599 geomtag = shellmark(*sface);
7601 if (issubface(*iedge)) {
7602 tspivot(*iedge, iface);
7608 }
else if (issubseg(*iedge)) {
7609 tsspivot1(*iedge, iface);
7610 e1 = farsorg(iface);
7611 e2 = farsdest(iface);
7614 spivot(iface, parentsh);
7615 facemark = shellmark(parentsh);
7617 terminatetetgen(
this, 2);
7623 planelineint(p1, p2, p3, e1, e2, ip, &u);
7624 if ((types[0] == (
int) ACROSSFACE) ||
7625 (types[0] == (
int) ACROSSEDGE)) {
7628 printf(
"PLC Error: A segment and a facet intersect at point");
7629 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7630 printf(
" Segment: [%d,%d] #%d (%d)\n", pointmark(e1), pointmark(e2),
7631 shellmark(iface), facemark);
7632 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7633 pointmark(p2), pointmark(p3), geomtag);
7635 sevent.f_marker1 = facemark;
7636 sevent.s_marker1 = shellmark(iface);
7637 sevent.f_vertices1[0] = pointmark(e1);
7638 sevent.f_vertices1[1] = pointmark(e2);
7639 sevent.f_vertices1[2] = 0;
7640 sevent.f_marker2 = geomtag;
7641 sevent.s_marker2 = 0;
7642 sevent.f_vertices2[0] = pointmark(p1);
7643 sevent.f_vertices2[1] = pointmark(p2);
7644 sevent.f_vertices2[2] = pointmark(p3);
7645 sevent.int_point[0] = ip[0];
7646 sevent.int_point[1] = ip[1];
7647 sevent.int_point[2] = ip[2];
7649 printf(
"PLC Error: Two facets intersect at point");
7650 printf(
" (%g,%g,%g).\n", ip[0], ip[1], ip[2]);
7651 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(e1), pointmark(e2),
7652 pointmark(sorg(iface)), shellmark(iface));
7653 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(p1),
7654 pointmark(p2), pointmark(p3), geomtag);
7656 sevent.f_marker1 = shellmark(iface);
7657 sevent.s_marker1 = 0;
7658 sevent.f_vertices1[0] = pointmark(e1);
7659 sevent.f_vertices1[1] = pointmark(e2);
7660 sevent.f_vertices1[2] = pointmark(sorg(iface));
7661 sevent.f_marker2 = geomtag;
7662 sevent.s_marker2 = 0;
7663 sevent.f_vertices2[0] = pointmark(p1);
7664 sevent.f_vertices2[1] = pointmark(p2);
7665 sevent.f_vertices2[2] = pointmark(p3);
7666 sevent.int_point[0] = ip[0];
7667 sevent.int_point[1] = ip[1];
7668 sevent.int_point[2] = ip[2];
7670 }
else if (types[0] == (
int) ACROSSVERT) {
7672 point crosspt = NULL;
7675 }
else if (poss[0] == 1) {
7677 }
else if (poss[0] == 2) {
7680 terminatetetgen(
this, 2);
7682 if (!issteinerpoint(crosspt)) {
7684 printf(
"PLC Error: A vertex and a segment intersect at (%g,%g,%g)\n",
7685 crosspt[0], crosspt[1], crosspt[2]);
7686 printf(
" Vertex: #%d\n", pointmark(crosspt));
7687 printf(
" Segment: [%d,%d] #%d (%d)\n", pointmark(e1), pointmark(e2),
7688 shellmark(iface), facemark);
7690 sevent.f_marker1 = 0;
7691 sevent.s_marker1 = 0;
7692 sevent.f_vertices1[0] = pointmark(crosspt);
7693 sevent.f_vertices1[1] = 0;
7694 sevent.f_vertices1[2] = 0;
7695 sevent.f_marker2 = facemark;
7696 sevent.s_marker2 = shellmark(iface);
7697 sevent.f_vertices2[0] = pointmark(e1);
7698 sevent.f_vertices2[1] = pointmark(e2);
7699 sevent.f_vertices2[2] = 0;
7700 sevent.int_point[0] = crosspt[0];
7701 sevent.int_point[1] = crosspt[1];
7702 sevent.int_point[2] = crosspt[2];
7704 printf(
"PLC Error: A vertex and a facet intersect at (%g,%g,%g)\n",
7705 crosspt[0], crosspt[1], crosspt[2]);
7706 printf(
" Vertex: #%d\n", pointmark(crosspt));
7707 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7708 pointmark(p2), pointmark(p3), geomtag);
7710 sevent.f_marker1 = 0;
7711 sevent.s_marker1 = 0;
7712 sevent.f_vertices1[0] = pointmark(crosspt);
7713 sevent.f_vertices1[1] = 0;
7714 sevent.f_vertices1[2] = 0;
7715 sevent.f_marker2 = geomtag;
7716 sevent.s_marker2 = 0;
7717 sevent.f_vertices2[0] = pointmark(p1);
7718 sevent.f_vertices2[1] = pointmark(p2);
7719 sevent.f_vertices2[2] = pointmark(p3);
7720 sevent.int_point[0] = crosspt[0];
7721 sevent.int_point[1] = crosspt[1];
7722 sevent.int_point[2] = crosspt[2];
7726 terminatetetgen(
this, 2);
7728 }
else if ((types[0] == (
int) TOUCHFACE) ||
7729 (types[0] == (
int) TOUCHEDGE)) {
7731 point touchpt = NULL;
7733 touchpt = org(*iedge);
7734 }
else if (poss[1] == 1) {
7735 touchpt = dest(*iedge);
7737 terminatetetgen(
this, 2);
7739 if (!issteinerpoint(touchpt)) {
7740 printf(
"PLC Error: A vertex and a facet intersect at (%g,%g,%g)\n",
7741 touchpt[0], touchpt[1], touchpt[2]);
7742 printf(
" Vertex: #%d\n", pointmark(touchpt));
7743 printf(
" Facet: [%d,%d,%d] #%d\n", pointmark(p1),
7744 pointmark(p2), pointmark(p3), geomtag);
7746 sevent.f_marker1 = 0;
7747 sevent.s_marker1 = 0;
7748 sevent.f_vertices1[0] = pointmark(touchpt);
7749 sevent.f_vertices1[1] = 0;
7750 sevent.f_vertices1[2] = 0;
7751 sevent.f_marker2 = geomtag;
7752 sevent.s_marker2 = 0;
7753 sevent.f_vertices2[0] = pointmark(p1);
7754 sevent.f_vertices2[1] = pointmark(p2);
7755 sevent.f_vertices2[2] = pointmark(p3);
7756 sevent.int_point[0] = touchpt[0];
7757 sevent.int_point[1] = touchpt[1];
7758 sevent.int_point[2] = touchpt[2];
7761 terminatetetgen(
this, 2);
7763 }
else if (types[0] == (
int) SHAREVERT) {
7764 terminatetetgen(
this, 2);
7766 terminatetetgen(
this, 2);
7768 }
else if (intflag == 4) {
7769 if (types[0] == (
int) SHAREFACE) {
7770 printf(
"PLC Error: Two facets are overlapping.\n");
7771 printf(
" Facet 1: [%d,%d,%d] #%d\n", pointmark(e1),
7772 pointmark(e2), pointmark(e3), facemark);
7773 printf(
" Facet 2: [%d,%d,%d] #%d\n", pointmark(p1),
7774 pointmark(p2), pointmark(p3), geomtag);
7776 sevent.f_marker1 = facemark;
7777 sevent.s_marker1 = 0;
7778 sevent.f_vertices1[0] = pointmark(e1);
7779 sevent.f_vertices1[1] = pointmark(e2);
7780 sevent.f_vertices1[2] = pointmark(e3);
7781 sevent.f_marker2 = geomtag;
7782 sevent.s_marker2 = 0;
7783 sevent.f_vertices2[0] = pointmark(p1);
7784 sevent.f_vertices2[1] = pointmark(p2);
7785 sevent.f_vertices2[2] = pointmark(p3);
7787 terminatetetgen(
this, 2);
7790 terminatetetgen(
this, 2);
7793 terminatetetgen(
this, 3);
7830 void tetgenmesh::flip23(triface* fliptets,
int hullflag, flipconstraints *fc)
7832 triface topcastets[3], botcastets[3];
7833 triface newface, casface;
7834 point pa, pb, pc, pd, pe;
7835 REAL attrib, volume;
7841 if (oppo(fliptets[1]) == dummypoint) {
7843 newface = fliptets[0];
7844 fliptets[0] = fliptets[1];
7845 fliptets[1] = newface;
7849 if (org(fliptets[0]) == dummypoint) {
7851 enextself(fliptets[0]);
7852 eprevself(fliptets[1]);
7853 }
else if (dest(fliptets[0]) == dummypoint) {
7855 eprevself(fliptets[0]);
7856 enextself(fliptets[1]);
7863 pa = org(fliptets[0]);
7864 pb = dest(fliptets[0]);
7865 pc = apex(fliptets[0]);
7866 pd = oppo(fliptets[0]);
7867 pe = oppo(fliptets[1]);
7872 for (i = 0; i < 3; i++) {
7873 fnext(fliptets[0], topcastets[i]);
7874 enextself(fliptets[0]);
7876 for (i = 0; i < 3; i++) {
7877 fnext(fliptets[1], botcastets[i]);
7878 eprevself(fliptets[1]);
7882 fliptets[0].ver = 11;
7883 fliptets[1].ver = 11;
7884 setelemmarker(fliptets[0].tet, 0);
7885 setelemmarker(fliptets[1].tet, 0);
7887 if (checksubsegflag) {
7889 if (fliptets[0].tet[8] != NULL) {
7890 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
7891 fliptets[0].tet[8] = NULL;
7893 if (fliptets[1].tet[8] != NULL) {
7894 tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
7895 fliptets[1].tet[8] = NULL;
7898 if (checksubfaceflag) {
7900 if (fliptets[0].tet[9] != NULL) {
7901 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
7902 fliptets[0].tet[9] = NULL;
7904 if (fliptets[1].tet[9] != NULL) {
7905 tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
7906 fliptets[1].tet[9] = NULL;
7910 maketetrahedron(&(fliptets[2]));
7912 for (i = 0; i < numelemattrib; i++) {
7913 attrib = elemattribute(fliptets[0].tet, i);
7914 setelemattribute(fliptets[2].tet, i, attrib);
7917 volume = volumebound(fliptets[0].tet);
7918 setvolumebound(fliptets[2].tet, volume);
7923 if (pd != dummypoint) {
7924 setvertices(fliptets[0], pe, pd, pa, pb);
7925 setvertices(fliptets[1], pe, pd, pb, pc);
7927 if (pc != dummypoint) {
7928 setvertices(fliptets[2], pe, pd, pc, pa);
7930 setvertices(fliptets[2], pd, pe, pa, pc);
7931 esymself(fliptets[2]);
7936 setvertices(fliptets[0], pa, pb, pe, pd);
7937 setvertices(fliptets[1], pb, pc, pe, pd);
7938 setvertices(fliptets[2], pc, pa, pe, pd);
7940 for (i = 0; i < 3; i++) {
7941 eprevesymself(fliptets[i]);
7942 enextself(fliptets[i]);
7948 setvertices(fliptets[0], pe, pd, pa, pb);
7949 setvertices(fliptets[1], pe, pd, pb, pc);
7950 setvertices(fliptets[2], pe, pd, pc, pa);
7953 if (fc->remove_ndelaunay_edge) {
7954 REAL volneg[2], volpos[3], vol_diff;
7955 if (pd != dummypoint) {
7956 if (pc != dummypoint) {
7957 volpos[0] = tetprismvol(pe, pd, pa, pb);
7958 volpos[1] = tetprismvol(pe, pd, pb, pc);
7959 volpos[2] = tetprismvol(pe, pd, pc, pa);
7960 volneg[0] = tetprismvol(pa, pb, pc, pd);
7961 volneg[1] = tetprismvol(pb, pa, pc, pe);
7963 volpos[0] = tetprismvol(pe, pd, pa, pb);
7974 volneg[1] = tetprismvol(pb, pa, pc, pe);
7976 vol_diff = volpos[0] + volpos[1] + volpos[2] - volneg[0] - volneg[1];
7977 fc->tetprism_vol_sum += vol_diff;
7981 for (i = 0; i < 3; i++) {
7982 esym(fliptets[i], newface);
7983 bond(newface, fliptets[(i + 1) % 3]);
7986 for (i = 0; i < 3; i++) {
7987 eorgoppo(fliptets[i], newface);
7988 bond(newface, topcastets[i]);
7991 for (i = 0; i < 3; i++) {
7992 edestoppo(fliptets[i], newface);
7993 bond(newface, botcastets[i]);
7996 if (checksubsegflag) {
8001 for (i = 0; i < 3; i++) {
8002 if (issubseg(topcastets[i])) {
8003 tsspivot1(topcastets[i], checkseg);
8004 eorgoppo(fliptets[i], newface);
8005 tssbond1(newface, checkseg);
8006 sstbond1(checkseg, newface);
8007 if (fc->chkencflag & 1) {
8008 enqueuesubface(badsubsegs, &checkseg);
8013 for (i = 0; i < 3; i++) {
8014 eprev(topcastets[i], casface);
8015 if (issubseg(casface)) {
8016 tsspivot1(casface, checkseg);
8017 enext(fliptets[i], newface);
8018 tssbond1(newface, checkseg);
8019 sstbond1(checkseg, newface);
8020 esym(fliptets[(i + 2) % 3], newface);
8022 tssbond1(newface, checkseg);
8023 sstbond1(checkseg, newface);
8024 if (fc->chkencflag & 1) {
8025 enqueuesubface(badsubsegs, &checkseg);
8030 for (i = 0; i < 3; i++) {
8031 enext(botcastets[i], casface);
8032 if (issubseg(casface)) {
8033 tsspivot1(casface, checkseg);
8034 eprev(fliptets[i], newface);
8035 tssbond1(newface, checkseg);
8036 sstbond1(checkseg, newface);
8037 esym(fliptets[(i + 2) % 3], newface);
8039 tssbond1(newface, checkseg);
8040 sstbond1(checkseg, newface);
8041 if (fc->chkencflag & 1) {
8042 enqueuesubface(badsubsegs, &checkseg);
8048 if (checksubfaceflag) {
8051 for (i = 0; i < 3; i++) {
8052 if (issubface(topcastets[i])) {
8053 tspivot(topcastets[i], checksh);
8054 eorgoppo(fliptets[i], newface);
8056 tsbond(newface, checksh);
8057 if (fc->chkencflag & 2) {
8058 enqueuesubface(badsubfacs, &checksh);
8062 for (i = 0; i < 3; i++) {
8063 if (issubface(botcastets[i])) {
8064 tspivot(botcastets[i], checksh);
8065 edestoppo(fliptets[i], newface);
8067 tsbond(newface, checksh);
8068 if (fc->chkencflag & 2) {
8069 enqueuesubface(badsubfacs, &checksh);
8075 if (fc->chkencflag & 4) {
8077 for (i = 0; i < 3; i++) {
8078 enqueuetetrahedron(&(fliptets[i]));
8083 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8084 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8085 setpoint2tet(pc, (tetrahedron) fliptets[1].tet);
8086 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8087 setpoint2tet(pe, (tetrahedron) fliptets[0].tet);
8090 if (dummyflag != 0) {
8092 if (dummyflag == -1) {
8094 for (i = 0; i < 3; i++) {
8095 esymself(fliptets[i]);
8098 newface = fliptets[1];
8099 fliptets[1] = fliptets[2];
8100 fliptets[2] = newface;
8103 if (dummyflag == 1) {
8105 newface = fliptets[0];
8106 fliptets[0] = fliptets[2];
8107 fliptets[2] = fliptets[1];
8108 fliptets[1] = newface;
8111 newface = fliptets[0];
8112 fliptets[0] = fliptets[1];
8113 fliptets[1] = fliptets[2];
8114 fliptets[2] = newface;
8120 if (fc->enqflag > 0) {
8122 for (i = 0; i < 3; i++) {
8123 eprevesym(fliptets[i], newface);
8124 flippush(flipstack, &newface);
8126 if (fc->enqflag > 1) {
8127 for (i = 0; i < 3; i++) {
8128 enextesym(fliptets[i], newface);
8129 flippush(flipstack, &newface);
8134 recenttet = fliptets[0];
8169 void tetgenmesh::flip32(triface* fliptets,
int hullflag, flipconstraints *fc)
8171 triface topcastets[3], botcastets[3];
8172 triface newface, casface;
8175 point pa, pb, pc, pd, pe;
8176 REAL attrib, volume;
8178 int spivot = -1, scount = 0;
8184 if (org(fliptets[0]) == dummypoint) {
8186 for (i = 0; i < 3; i++) {
8187 esymself(fliptets[i]);
8190 newface = fliptets[1];
8191 fliptets[1] = fliptets[2];
8192 fliptets[2] = newface;
8196 if (apex(fliptets[0]) == dummypoint) {
8198 newface = fliptets[0];
8199 fliptets[0] = fliptets[1];
8200 fliptets[1] = fliptets[2];
8201 fliptets[2] = newface;
8202 }
else if (apex(fliptets[1]) == dummypoint) {
8204 newface = fliptets[0];
8205 fliptets[0] = fliptets[2];
8206 fliptets[2] = fliptets[1];
8207 fliptets[1] = newface;
8214 pa = apex(fliptets[0]);
8215 pb = apex(fliptets[1]);
8216 pc = apex(fliptets[2]);
8217 pd = dest(fliptets[0]);
8218 pe = org(fliptets[0]);
8223 for (i = 0; i < 3; i++) {
8224 eorgoppo(fliptets[i], casface);
8225 fsym(casface, topcastets[i]);
8227 for (i = 0; i < 3; i++) {
8228 edestoppo(fliptets[i], casface);
8229 fsym(casface, botcastets[i]);
8232 if (checksubfaceflag) {
8234 for (i = 0; i < 3; i++) {
8235 tspivot(fliptets[i], flipshs[i]);
8236 if (flipshs[i].sh != NULL) {
8238 stdissolve(flipshs[i]);
8247 fliptets[0].ver = 11;
8248 fliptets[1].ver = 11;
8249 setelemmarker(fliptets[0].tet, 0);
8250 setelemmarker(fliptets[1].tet, 0);
8251 if (checksubsegflag) {
8253 if (fliptets[0].tet[8] != NULL) {
8254 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
8255 fliptets[0].tet[8] = NULL;
8257 if (fliptets[1].tet[8] != NULL) {
8258 tet2segpool->dealloc((shellface *) fliptets[1].tet[8]);
8259 fliptets[1].tet[8] = NULL;
8262 if (checksubfaceflag) {
8264 if (fliptets[0].tet[9] != NULL) {
8265 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
8266 fliptets[0].tet[9] = NULL;
8268 if (fliptets[1].tet[9] != NULL) {
8269 tet2subpool->dealloc((shellface *) fliptets[1].tet[9]);
8270 fliptets[1].tet[9] = NULL;
8273 if (checksubfaceflag) {
8283 for (j = 0; j < 2; j++) {
8284 for (i = 0; i < numelemattrib; i++) {
8285 attrib = elemattribute(fliptets[spivot].tet, i);
8286 setelemattribute(fliptets[j].tet, i, attrib);
8289 volume = volumebound(fliptets[spivot].tet);
8290 setvolumebound(fliptets[j].tet, volume);
8296 tetrahedrondealloc(fliptets[2].tet);
8300 if (pc != dummypoint) {
8302 if (pd != dummypoint) {
8308 setvertices(fliptets[0], pa, pb, pc, pd);
8309 setvertices(fliptets[1], pb, pa, pc, pe);
8312 setvertices(fliptets[0], pb, pa, pd, pc);
8313 setvertices(fliptets[1], pa, pb, pe, pc);
8315 esymself(fliptets[0]);
8317 esymself(fliptets[1]);
8321 setvertices(fliptets[0], pa, pb, pc, pd);
8322 setvertices(fliptets[1], pb, pa, pc, pe);
8325 if (fc->remove_ndelaunay_edge) {
8326 REAL volneg[3], volpos[2], vol_diff;
8327 if (pc != dummypoint) {
8328 if (pd != dummypoint) {
8329 volneg[0] = tetprismvol(pe, pd, pa, pb);
8330 volneg[1] = tetprismvol(pe, pd, pb, pc);
8331 volneg[2] = tetprismvol(pe, pd, pc, pa);
8332 volpos[0] = tetprismvol(pa, pb, pc, pd);
8333 volpos[1] = tetprismvol(pb, pa, pc, pe);
8339 volpos[1] = tetprismvol(pb, pa, pc, pe);
8342 volneg[0] = tetprismvol(pe, pd, pa, pb);
8348 vol_diff = volpos[0] + volpos[1] - volneg[0] - volneg[1] - volneg[2];
8349 fc->tetprism_vol_sum += vol_diff;
8353 bond(fliptets[0], fliptets[1]);
8355 for (i = 0; i < 3; i++) {
8356 esym(fliptets[0], newface);
8357 bond(newface, topcastets[i]);
8358 enextself(fliptets[0]);
8361 for (i = 0; i < 3; i++) {
8362 esym(fliptets[1], newface);
8363 bond(newface, botcastets[i]);
8364 eprevself(fliptets[1]);
8367 if (checksubsegflag) {
8369 for (i = 0; i < 3; i++) {
8370 if (issubseg(topcastets[i])) {
8371 tsspivot1(topcastets[i], checkseg);
8372 tssbond1(fliptets[0], checkseg);
8373 sstbond1(checkseg, fliptets[0]);
8374 tssbond1(fliptets[1], checkseg);
8375 sstbond1(checkseg, fliptets[1]);
8376 if (fc->chkencflag & 1) {
8377 enqueuesubface(badsubsegs, &checkseg);
8380 enextself(fliptets[0]);
8381 eprevself(fliptets[1]);
8384 for (i = 0; i < 3; i++) {
8385 esym(fliptets[0], newface);
8387 enext(topcastets[i], casface);
8388 if (issubseg(casface)) {
8389 tsspivot1(casface, checkseg);
8390 tssbond1(newface, checkseg);
8391 sstbond1(checkseg, newface);
8392 if (fc->chkencflag & 1) {
8393 enqueuesubface(badsubsegs, &checkseg);
8396 enextself(fliptets[0]);
8399 for (i = 0; i < 3; i++) {
8400 esym(fliptets[1], newface);
8402 eprev(botcastets[i], casface);
8403 if (issubseg(casface)) {
8404 tsspivot1(casface, checkseg);
8405 tssbond1(newface, checkseg);
8406 sstbond1(checkseg, newface);
8407 if (fc->chkencflag & 1) {
8408 enqueuesubface(badsubsegs, &checkseg);
8411 eprevself(fliptets[1]);
8415 if (checksubfaceflag) {
8418 for (i = 0; i < 3; i++) {
8419 if (issubface(topcastets[i])) {
8420 tspivot(topcastets[i], checksh);
8421 esym(fliptets[0], newface);
8423 tsbond(newface, checksh);
8424 if (fc->chkencflag & 2) {
8425 enqueuesubface(badsubfacs, &checksh);
8428 enextself(fliptets[0]);
8431 for (i = 0; i < 3; i++) {
8432 if (issubface(botcastets[i])) {
8433 tspivot(botcastets[i], checksh);
8434 esym(fliptets[1], newface);
8436 tsbond(newface, checksh);
8437 if (fc->chkencflag & 2) {
8438 enqueuesubface(badsubfacs, &checksh);
8441 eprevself(fliptets[1]);
8447 flipfaces[0] = flipshs[(spivot + 1) % 3];
8448 flipfaces[1] = flipshs[(spivot + 2) % 3];
8449 sesymself(flipfaces[1]);
8450 flip22(flipfaces, 0, fc->chkencflag);
8454 topcastets[0] = fliptets[0];
8455 botcastets[0] = fliptets[1];
8456 for (i = 0; i < ((spivot + 1) % 3); i++) {
8457 enextself(topcastets[0]);
8458 eprevself(botcastets[0]);
8461 esymself(topcastets[0]);
8462 sesymself(flipfaces[0]);
8464 tspivot(topcastets[0], checksh);
8465 if (checksh.sh == NULL) {
8466 tsbond(topcastets[0], flipfaces[0]);
8467 fsymself(topcastets[0]);
8468 sesymself(flipfaces[0]);
8469 tsbond(topcastets[0], flipfaces[0]);
8472 terminatetetgen(
this, 2);
8475 esymself(botcastets[0]);
8476 sesymself(flipfaces[1]);
8478 tspivot(botcastets[0], checksh);
8479 if (checksh.sh == NULL) {
8480 tsbond(botcastets[0], flipfaces[1]);
8481 fsymself(botcastets[0]);
8482 sesymself(flipfaces[1]);
8483 tsbond(botcastets[0], flipfaces[1]);
8486 terminatetetgen(
this, 2);
8491 if (fc->chkencflag & 4) {
8493 for (i = 0; i < 2; i++) {
8494 enqueuetetrahedron(&(fliptets[i]));
8498 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8499 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8500 setpoint2tet(pc, (tetrahedron) fliptets[0].tet);
8501 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8502 setpoint2tet(pe, (tetrahedron) fliptets[1].tet);
8505 if (dummyflag != 0) {
8507 if (dummyflag == -1) {
8509 newface = fliptets[0];
8510 fliptets[0] = fliptets[1];
8511 fliptets[1] = newface;
8514 if (dummyflag == 1) {
8515 eprevself(fliptets[0]);
8516 enextself(fliptets[1]);
8518 enextself(fliptets[0]);
8519 eprevself(fliptets[1]);
8525 if (fc->enqflag > 0) {
8528 enextesym(fliptets[0], newface);
8529 flippush(flipstack, &newface);
8530 eprevesym(fliptets[1], newface);
8531 flippush(flipstack, &newface);
8532 if (fc->enqflag > 1) {
8534 eprevesym(fliptets[0], newface);
8535 flippush(flipstack, &newface);
8536 enextesym(fliptets[1], newface);
8537 flippush(flipstack, &newface);
8539 esym(fliptets[0], newface);
8540 flippush(flipstack, &newface);
8541 esym(fliptets[1], newface);
8542 flippush(flipstack, &newface);
8546 recenttet = fliptets[0];
8571 void tetgenmesh::flip41(triface* fliptets,
int hullflag, flipconstraints *fc)
8573 triface topcastets[3], botcastet;
8574 triface newface, neightet;
8576 point pa, pb, pc, pd, pp;
8578 int spivot = -1, scount = 0;
8582 pa = org(fliptets[3]);
8583 pb = dest(fliptets[3]);
8584 pc = apex(fliptets[3]);
8585 pd = dest(fliptets[0]);
8586 pp = org(fliptets[0]);
8591 for (i = 0; i < 3; i++) {
8592 enext(fliptets[i], topcastets[i]);
8593 fnextself(topcastets[i]);
8594 enextself(topcastets[i]);
8596 fsym(fliptets[3], botcastet);
8598 if (checksubfaceflag) {
8601 for (i = 0; i < 3; i++) {
8602 fnext(fliptets[3], newface);
8603 tspivot(newface, flipshs[i]);
8604 if (flipshs[i].sh != NULL) {
8608 enextself(fliptets[3]);
8615 fsym(topcastets[spivot], neightet);
8617 for (i = 0; i < 3; i++) {
8618 esym(neightet, newface);
8619 tspivot(newface, flipshs[i]);
8620 eprevself(neightet);
8630 fliptets[0].ver = 11;
8631 setelemmarker(fliptets[0].tet, 0);
8633 if (checksubsegflag) {
8635 if (fliptets[0].tet[8] != NULL) {
8636 tet2segpool->dealloc((shellface *) fliptets[0].tet[8]);
8637 fliptets[0].tet[8] = NULL;
8640 if (checksubfaceflag) {
8642 if (fliptets[0].tet[9] != NULL) {
8643 tet2subpool->dealloc((shellface *) fliptets[0].tet[9]);
8644 fliptets[0].tet[9] = NULL;
8648 for (i = 1; i < 4; i++) {
8649 tetrahedrondealloc(fliptets[i].tet);
8652 if (pp != dummypoint) {
8654 setpointtype(pp, UNUSEDVERTEX);
8661 if (pa == dummypoint) {
8663 setvertices(fliptets[0], pc, pb, pd, pa);
8664 esymself(fliptets[0]);
8665 eprevself(fliptets[0]);
8667 }
else if (pb == dummypoint) {
8668 setvertices(fliptets[0], pa, pc, pd, pb);
8669 esymself(fliptets[0]);
8670 enextself(fliptets[0]);
8672 }
else if (pc == dummypoint) {
8673 setvertices(fliptets[0], pb, pa, pd, pc);
8674 esymself(fliptets[0]);
8676 }
else if (pd == dummypoint) {
8677 setvertices(fliptets[0], pa, pb, pc, pd);
8680 setvertices(fliptets[0], pa, pb, pc, pd);
8681 if (pp == dummypoint) {
8687 if (dummyflag > 0) {
8690 }
else if (dummyflag < 0) {
8696 setvertices(fliptets[0], pa, pb, pc, pd);
8699 if (fc->remove_ndelaunay_edge) {
8700 REAL volneg[4], volpos[1], vol_diff;
8701 if (dummyflag > 0) {
8702 if (pa == dummypoint) {
8704 volneg[1] = tetprismvol(pp, pd, pb, pc);
8707 }
else if (pb == dummypoint) {
8710 volneg[2] = tetprismvol(pp, pd, pc, pa);
8712 }
else if (pc == dummypoint) {
8713 volneg[0] = tetprismvol(pp, pd, pa, pb);
8721 volneg[3] = tetprismvol(pa, pb, pc, pp);
8724 }
else if (dummyflag < 0) {
8729 volpos[0] = tetprismvol(pa, pb, pc, pd);
8731 volneg[0] = tetprismvol(pp, pd, pa, pb);
8732 volneg[1] = tetprismvol(pp, pd, pb, pc);
8733 volneg[2] = tetprismvol(pp, pd, pc, pa);
8734 volneg[3] = tetprismvol(pa, pb, pc, pp);
8735 volpos[0] = tetprismvol(pa, pb, pc, pd);
8737 vol_diff = volpos[0] - volneg[0] - volneg[1] - volneg[2] - volneg[3];
8738 fc->tetprism_vol_sum += vol_diff;
8742 for (i = 0; i < 3; i++) {
8743 esym(fliptets[0], newface);
8744 bond(newface, topcastets[i]);
8745 enextself(fliptets[0]);
8747 bond(fliptets[0], botcastet);
8749 if (checksubsegflag) {
8752 for (i = 0; i < 3; i++) {
8753 eprev(topcastets[i], newface);
8754 if (issubseg(newface)) {
8755 tsspivot1(newface, checkseg);
8756 esym(fliptets[0], newface);
8758 tssbond1(newface, checkseg);
8759 sstbond1(checkseg, newface);
8760 if (fc->chkencflag & 1) {
8761 enqueuesubface(badsubsegs, &checkseg);
8764 enextself(fliptets[0]);
8766 for (i = 0; i < 3; i++) {
8767 if (issubseg(topcastets[i])) {
8768 tsspivot1(topcastets[i], checkseg);
8769 tssbond1(fliptets[0], checkseg);
8770 sstbond1(checkseg, fliptets[0]);
8771 if (fc->chkencflag & 1) {
8772 enqueuesubface(badsubsegs, &checkseg);
8775 enextself(fliptets[0]);
8779 if (checksubfaceflag) {
8782 for (i = 0; i < 3; i++) {
8783 if (issubface(topcastets[i])) {
8784 tspivot(topcastets[i], checksh);
8785 esym(fliptets[0], newface);
8787 tsbond(newface, checksh);
8788 if (fc->chkencflag & 2) {
8789 enqueuesubface(badsubfacs, &checksh);
8792 enextself(fliptets[0]);
8794 if (issubface(botcastet)) {
8795 tspivot(botcastet, checksh);
8797 tsbond(fliptets[0], checksh);
8798 if (fc->chkencflag & 2) {
8799 enqueuesubface(badsubfacs, &checksh);
8812 for (i = 0; i < 3; i++) {
8813 senext2self(flipshs[i]);
8817 for (i = 0; i < 3; i++) {
8818 shellfacedealloc(subfaces, flipshs[i].sh);
8822 tsbond(topcastets[spivot], flipshs[3]);
8823 fsym(topcastets[spivot], newface);
8824 sesym(flipshs[3], checksh);
8825 tsbond(newface, checksh);
8828 tsbond(fliptets[0], flipshs[3]);
8829 fsym(fliptets[0], newface);
8830 sesym(flipshs[3], checksh);
8831 tsbond(newface, checksh);
8836 if (fc->chkencflag & 4) {
8837 enqueuetetrahedron(&(fliptets[0]));
8841 setpoint2tet(pa, (tetrahedron) fliptets[0].tet);
8842 setpoint2tet(pb, (tetrahedron) fliptets[0].tet);
8843 setpoint2tet(pc, (tetrahedron) fliptets[0].tet);
8844 setpoint2tet(pd, (tetrahedron) fliptets[0].tet);
8846 if (fc->enqflag > 0) {
8848 flippush(flipstack, &(fliptets[0]));
8849 if (fc->enqflag > 1) {
8850 for (i = 0; i < 3; i++) {
8851 esym(fliptets[0], newface);
8852 flippush(flipstack, &newface);
8853 enextself(fliptets[0]);
8858 recenttet = fliptets[0];
8890 int tetgenmesh::flipnm(triface* abtets,
int n,
int level,
int abedgepivot,
8891 flipconstraints* fc)
8893 triface fliptets[3], spintet, flipedge;
8894 triface *tmpabtets, *parytet;
8895 point pa, pb, pc, pd, pe, pf;
8897 int hullflag, hulledgeflag;
8898 int reducflag, rejflag;
8899 int reflexlinkedgecount;
8905 pa = org(abtets[0]);
8906 pb = dest(abtets[0]);
8910 reflexlinkedgecount = 0;
8912 for (i = 0; i < n; i++) {
8914 if (checksubfaceflag) {
8915 if (issubface(abtets[i])) {
8920 if ((elemcounter(abtets[i]) > 1) ||
8921 (elemcounter(abtets[(i - 1 + n) % n]) > 1)) {
8925 pc = apex(abtets[i]);
8926 pd = apex(abtets[(i + 1) % n]);
8927 pe = apex(abtets[(i - 1 + n) % n]);
8928 if ((pd == dummypoint) || (pe == dummypoint)) {
8936 hullflag = (pc == dummypoint);
8938 if (hullflag == 0) {
8939 ori = orient3d(pb, pc, pd, pe);
8941 ori = orient3d(pc, pa, pd, pe);
8944 ori = orient3d(pa, pb, pd, pe);
8948 }
else if (ori == 0) {
8954 pf = apex(abtets[(i + 2) % n]);
8955 hulledgeflag = (pf == dummypoint);
8961 reflexlinkedgecount++;
8972 pf = apex(abtets[(i + 2) % n]);
8973 ori = orient3d(pd, pe, pf, pa);
8975 ori = orient3d(pe, pd, pf, pb);
8987 if (nonconvex && hulledgeflag) {
8989 if (getedge(pe, pd, &spintet)) {
8999 if (fc->checkflipeligibility) {
9001 rejflag = checkflipeligibility(1, pa, pb, pc, pd, pe, level,
9006 fliptets[0] = abtets[i];
9007 fsym(fliptets[0], fliptets[1]);
9008 flip23(fliptets, hullflag, fc);
9026 edestoppoself(fliptets[0]);
9028 increaseelemcounter(fliptets[0]);
9029 abtets[(i - 1 + n) % n] = fliptets[0];
9030 for (j = i; j < n - 1; j++) {
9031 abtets[j] = abtets[j + 1];
9038 abtets[n - 1].tet = (tetrahedron *) pc;
9039 abtets[n - 1].ver = 0;
9042 abtets[n - 1].ver |= (1 << 4);
9044 abtets[n - 1].ver |= (i << 6);
9046 if (fc->collectnewtets) {
9049 for (j = 1; j < 3; j++) {
9050 cavetetlist->newindex((
void **) &parytet);
9051 *parytet = fliptets[j];
9056 nn = flipnm(abtets, n - 1, level, abedgepivot, fc);
9063 if (fc->unflip || (ori == 0)) {
9070 fliptets[0] = abtets[(i-1 + (n-1)) % (n-1)];
9071 edestoppoself(fliptets[0]);
9072 fnext(fliptets[0], fliptets[1]);
9073 fnext(fliptets[1], fliptets[2]);
9075 flip32(fliptets, hullflag, fc);
9077 for (j = 0; j < 2; j++) {
9078 increaseelemcounter(fliptets[j]);
9081 for (j = n - 2; j>= i; j--) {
9082 abtets[j + 1] = abtets[j];
9087 esym(fliptets[1], abtets[(i - 1 + n) % n]);
9088 abtets[i] = fliptets[0];
9090 if (fc->collectnewtets) {
9092 cavetetlist->objects -= 2;
9109 if (reflexlinkedgecount > 0) {
9111 if (((b->fliplinklevel < 0) && (level < autofliplinklevel)) ||
9112 ((b->fliplinklevel >= 0) && (level < b->fliplinklevel))) {
9114 for (i = 0; i < n; i++) {
9116 if ((elemcounter(abtets[i]) > 1) ||
9117 (elemcounter(abtets[(i - 1 + n) % n]) > 1)) {
9120 pc = apex(abtets[i]);
9121 if (pc == dummypoint) {
9124 pd = apex(abtets[(i + 1) % n]);
9125 pe = apex(abtets[(i - 1 + n) % n]);
9126 if ((pd == dummypoint) || (pe == dummypoint)) {
9134 ori = orient3d(pb, pc, pd, pe);
9137 enext(abtets[i], flipedge);
9142 ori = orient3d(pc, pa, pd, pe);
9145 eprev(abtets[i], flipedge);
9150 if (!edgepivot)
continue;
9153 if (checksubsegflag) {
9155 if (issubseg(flipedge)) {
9156 if (fc->collectencsegflag) {
9157 face checkseg, *paryseg;
9158 tsspivot1(flipedge, checkseg);
9159 if (!sinfected(checkseg)) {
9162 caveencseglist->newindex((
void **) &paryseg);
9163 *paryseg = checkseg;
9178 j += (elemcounter(spintet));
9180 if (spintet.tet == flipedge.tet)
break;
9185 terminatetetgen(
this, 2);
9192 if ((b->flipstarsize > 0) && (n1 > b->flipstarsize)) {
9198 tmpabtets =
new triface[n1];
9203 tmpabtets[j] = spintet;
9205 increaseelemcounter(tmpabtets[j]);
9208 if (spintet.tet == flipedge.tet)
break;
9212 nn = flipnm(tmpabtets, n1, level + 1, edgepivot, fc);
9217 if (edgepivot == 1) {
9219 spintet = tmpabtets[0];
9225 spintet = tmpabtets[1];
9230 increaseelemcounter(spintet);
9232 abtets[(i - 1 + n) % n] = spintet;
9233 for (j = i; j < n - 1; j++) {
9234 abtets[j] = abtets[j + 1];
9238 abtets[n - 1].tet = (tetrahedron *) tmpabtets;
9239 abtets[n - 1].ver = 0;
9241 abtets[n - 1].ver |= edgepivot;
9243 abtets[n - 1].ver |= (1 << 5);
9245 abtets[n - 1].ver |= (i << 6);
9247 abtets[n - 1].ver |= (n1 << 19);
9251 tmpabtets[0].tet = (tetrahedron *) pc;
9252 tmpabtets[0].ver = (1 << 5);
9255 nn = flipnm(abtets, n - 1, level, abedgepivot, fc);
9268 if (edgepivot == 1) {
9270 tmpabtets[0] = abtets[((i-1)+(n-1))%(n-1)];
9271 eprevself(tmpabtets[0]);
9272 esymself(tmpabtets[0]);
9273 eprevself(tmpabtets[0]);
9274 fsym(tmpabtets[0], tmpabtets[1]);
9277 tmpabtets[1] = abtets[((i-1)+(n-1))%(n-1)];
9278 enextself(tmpabtets[1]);
9279 esymself(tmpabtets[1]);
9280 enextself(tmpabtets[1]);
9281 fsym(tmpabtets[1], tmpabtets[0]);
9285 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9288 for (j = n - 2; j >= i; j--) {
9289 abtets[j + 1] = abtets[j];
9291 if (edgepivot == 1) {
9295 fliptets[0] = tmpabtets[1];
9296 enextself(fliptets[0]);
9297 esymself(fliptets[0]);
9298 fliptets[1] = tmpabtets[0];
9299 esymself(fliptets[1]);
9300 eprevself(fliptets[1]);
9305 fliptets[0] = tmpabtets[1];
9306 eprevself(fliptets[0]);
9307 esymself(fliptets[0]);
9308 fliptets[1] = tmpabtets[0];
9309 esymself(fliptets[1]);
9310 enextself(fliptets[1]);
9312 for (j = 0; j < 2; j++) {
9313 increaseelemcounter(fliptets[j]);
9316 abtets[(i - 1 + n) % n] = fliptets[0];
9317 abtets[i] = fliptets[1];
9320 delete [] tmpabtets;
9335 flipnm_post(tmpabtets, n1, nn, edgepivot, fc);
9338 for (j = 0; j < nn; j++) {
9339 decreaseelemcounter(tmpabtets[j]);
9342 delete [] tmpabtets;
9353 if (apex(abtets[0]) == dummypoint) {
9354 pc = apex(abtets[1]);
9355 pd = apex(abtets[2]);
9356 pe = apex(abtets[0]);
9358 }
else if (apex(abtets[1]) == dummypoint) {
9359 pc = apex(abtets[2]);
9360 pd = apex(abtets[0]);
9361 pe = apex(abtets[1]);
9364 pc = apex(abtets[0]);
9365 pd = apex(abtets[1]);
9366 pe = apex(abtets[2]);
9367 hullflag = (pe == dummypoint) ? 3 : 0;
9374 if (hullflag == 0) {
9377 ori = orient3d(pd, pc, pe, pa);
9379 ori = orient3d(pc, pd, pe, pb);
9390 ori = orient3d(pa, pb, pc, pd);
9397 if (reducflag == 1) {
9400 point searchpt = NULL, chkpt;
9401 REAL bigvol = 0.0, ori1, ori2;
9406 fliptets[0] = abtets[hullflag % 3];
9407 eorgoppoself(fliptets[0]);
9408 spintet = fliptets[0];
9411 chkpt = oppo(spintet);
9412 if (chkpt == pb)
break;
9413 if ((chkpt != dummypoint) && (apex(spintet) != dummypoint)) {
9414 ori = -orient3d(pd, pc, apex(spintet), chkpt);
9421 if (searchpt != NULL) {
9423 ori1 = orient3d(pd, pc, searchpt, pa);
9424 ori2 = orient3d(pd, pc, searchpt, pb);
9425 if (ori1 * ori2 >= 0.0) {
9428 ori1 = orient3d(pa, pb, searchpt, pc);
9429 ori2 = orient3d(pa, pb, searchpt, pd);
9430 if (ori1 * ori2 >= 0.0) {
9443 if (checksubfaceflag) {
9450 for (j = 0; j < 3; j++) {
9451 if (issubface(abtets[j])) {
9462 }
else if (nn == 2) {
9465 eorgoppo(abtets[(edgepivot + 1) % 3], spintet);
9466 if (issubface(spintet)) {
9470 if (issubface(spintet)) {
9474 }
else if (nn == 3) {
9476 terminatetetgen(
this, 2);
9479 if (!rejflag && fc->checkflipeligibility) {
9484 rejflag = checkflipeligibility(2, pc, pd, pe, pb, pa, level,
9489 flip32(abtets, hullflag, fc);
9490 if (fc->remove_ndelaunay_edge) {
9494 if ((fc->tetprism_vol_sum >= 0.0) ||
9495 (fabs(fc->tetprism_vol_sum) < fc->bak_tetprism_vol)) {
9497 flip23(abtets, hullflag, fc);
9499 for (j = 0; j < 3; j++) {
9500 increaseelemcounter(abtets[j]);
9506 if (fc->collectnewtets) {
9510 for (j = 0; j < 2; j++) {
9511 cavetetlist->newindex((
void **) &parytet);
9512 *parytet = abtets[j];
9517 cavetetlist->newindex((
void **) &parytet);
9518 if (abedgepivot == 1) {
9519 *parytet = abtets[1];
9521 *parytet = abtets[0];
9564 int tetgenmesh::flipnm_post(triface* abtets,
int n,
int nn,
int abedgepivot,
9565 flipconstraints* fc)
9567 triface fliptets[3], flipface;
9581 flip23(abtets, 1, fc);
9582 if (fc->collectnewtets) {
9584 if (abedgepivot == 0) {
9586 cavetetlist->objects -= 2;
9589 cavetetlist->objects -= 1;
9598 for (i = nn; i < n; i++) {
9602 fliptype = ((abtets[i].ver >> 4) & 3);
9603 if (fliptype == 1) {
9605 t = (abtets[i].ver >> 6);
9607 if (b->verbose > 2) {
9608 printf(
" Recover a 2-to-3 flip at f[%d].\n", t);
9612 fliptets[0] = abtets[((t - 1) + i) % i];
9613 eprevself(fliptets[0]);
9614 esymself(fliptets[0]);
9615 enextself(fliptets[0]);
9616 fnext(fliptets[0], fliptets[1]);
9617 fnext(fliptets[1], fliptets[2]);
9620 flip32(fliptets, 1, fc);
9623 for (j = i - 1; j >= t; j--) {
9624 abtets[j + 1] = abtets[j];
9629 esym(fliptets[1], abtets[((t-1) + (i+1)) % (i+1)]);
9630 abtets[t] = fliptets[0];
9631 if (fc->collectnewtets) {
9633 cavetetlist->objects -= 2;
9636 }
else if (fliptype == 2) {
9637 tmpabtets = (triface *) (abtets[i].tet);
9638 n1 = ((abtets[i].ver >> 19) & 8191);
9639 edgepivot = (abtets[i].ver & 3);
9640 t = ((abtets[i].ver >> 6) & 8191);
9642 if (b->verbose > 2) {
9643 printf(
" Recover a %d-to-m flip at e[%d] of f[%d].\n", n1,
9650 if (edgepivot == 1) {
9652 tmpabtets[0] = abtets[(t - 1 + i) % i];
9653 eprevself(tmpabtets[0]);
9654 esymself(tmpabtets[0]);
9655 eprevself(tmpabtets[0]);
9656 fsym(tmpabtets[0], tmpabtets[1]);
9659 tmpabtets[1] = abtets[(t - 1 + i) % i];
9660 enextself(tmpabtets[1]);
9661 esymself(tmpabtets[1]);
9662 enextself(tmpabtets[1]);
9663 fsym(tmpabtets[1], tmpabtets[0]);
9667 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9670 for (j = i - 1; j >= t; j--) {
9671 abtets[j + 1] = abtets[j];
9673 if (edgepivot == 1) {
9677 fliptets[0] = tmpabtets[1];
9678 enextself(fliptets[0]);
9679 esymself(fliptets[0]);
9680 fliptets[1] = tmpabtets[0];
9681 esymself(fliptets[1]);
9682 eprevself(fliptets[1]);
9687 fliptets[0] = tmpabtets[1];
9688 eprevself(fliptets[0]);
9689 esymself(fliptets[0]);
9690 fliptets[1] = tmpabtets[0];
9691 esymself(fliptets[1]);
9692 enextself(fliptets[1]);
9695 abtets[((t-1) + (i+1)) % (i+1)] = fliptets[0];
9696 abtets[t] = fliptets[1];
9700 flipnm_post(tmpabtets, n1, 2, edgepivot, fc);
9702 if (b->verbose > 2) {
9703 printf(
" Release %d spaces at f[%d].\n", n1, i);
9705 delete [] tmpabtets;
9727 int tetgenmesh::insertpoint(point insertpt, triface *searchtet, face *splitsh,
9728 face *splitseg, insertvertexflags *ivf)
9730 arraypool *swaplist;
9731 triface *cavetet, spintet, neightet, neineitet, *parytet;
9732 triface oldtet, newtet, newneitet;
9733 face checksh, neighsh, *parysh;
9734 face checkseg, *paryseg;
9735 point *pts, pa, pb, pc, *parypt;
9736 enum locateresult loc = OUTSIDE;
9738 REAL attrib, volume;
9743 if (b->verbose > 2) {
9744 printf(
" Insert point %d\n", pointmark(insertpt));
9748 if (searchtet->tet != NULL) {
9749 loc = (
enum locateresult) ivf->iloc;
9752 if (loc == OUTSIDE) {
9753 if (searchtet->tet == NULL) {
9755 randomsample(insertpt, searchtet);
9758 *searchtet = recenttet;
9762 loc = locate(insertpt, searchtet);
9765 ivf->iloc = (int) loc;
9768 if (loc != OUTSIDE) {
9770 pts = (point *) searchtet->tet;
9771 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt,
9772 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
9776 ivf->iloc = (int) NONREGULAR;
9787 if (loc == OUTSIDE) {
9791 for (i = 0; i < 4; i++) {
9792 decode(searchtet->tet[i], neightet);
9793 neightet.ver = epivot[neightet.ver];
9794 cavebdrylist->newindex((
void **) &parytet);
9795 *parytet = neightet;
9798 caveoldtetlist->newindex((
void **) &parytet);
9799 *parytet = *searchtet;
9800 }
else if (loc == INTETRAHEDRON) {
9803 for (i = 0; i < 4; i++) {
9804 decode(searchtet->tet[i], neightet);
9805 neightet.ver = epivot[neightet.ver];
9806 cavebdrylist->newindex((
void **) &parytet);
9807 *parytet = neightet;
9810 caveoldtetlist->newindex((
void **) &parytet);
9811 *parytet = *searchtet;
9812 }
else if (loc == ONFACE) {
9815 j = (searchtet->ver & 3);
9816 for (i = 1; i < 4; i++) {
9817 decode(searchtet->tet[(j + i) % 4], neightet);
9818 neightet.ver = epivot[neightet.ver];
9819 cavebdrylist->newindex((
void **) &parytet);
9820 *parytet = neightet;
9822 decode(searchtet->tet[j], spintet);
9823 j = (spintet.ver & 3);
9824 for (i = 1; i < 4; i++) {
9825 decode(spintet.tet[(j + i) % 4], neightet);
9826 neightet.ver = epivot[neightet.ver];
9827 cavebdrylist->newindex((
void **) &parytet);
9828 *parytet = neightet;
9831 caveoldtetlist->newindex((
void **) &parytet);
9834 caveoldtetlist->newindex((
void **) &parytet);
9835 *parytet = *searchtet;
9837 if (ivf->splitbdflag) {
9838 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
9840 smarktest(*splitsh);
9841 caveshlist->newindex((
void **) &parysh);
9845 }
else if (loc == ONEDGE) {
9848 spintet = *searchtet;
9850 eorgoppo(spintet, neightet);
9851 decode(neightet.tet[neightet.ver & 3], neightet);
9852 neightet.ver = epivot[neightet.ver];
9853 cavebdrylist->newindex((
void **) &parytet);
9854 *parytet = neightet;
9855 edestoppo(spintet, neightet);
9856 decode(neightet.tet[neightet.ver & 3], neightet);
9857 neightet.ver = epivot[neightet.ver];
9858 cavebdrylist->newindex((
void **) &parytet);
9859 *parytet = neightet;
9861 caveoldtetlist->newindex((
void **) &parytet);
9864 if (spintet.tet == searchtet->tet)
break;
9867 if (ivf->splitbdflag) {
9869 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
9870 smarktest(*splitseg);
9871 splitseg->shver = 0;
9872 spivot(*splitseg, *splitsh);
9874 if (splitsh != NULL) {
9875 if (splitsh->sh != NULL) {
9877 pa = sorg(*splitsh);
9881 if (sorg(neighsh) != pa) {
9886 caveshlist->newindex((
void **) &parysh);
9889 cavesegshlist->newindex((
void **) &parysh);
9892 spivotself(neighsh);
9894 if (neighsh.sh == splitsh->sh)
break;
9895 if (neighsh.sh == NULL)
break;
9900 }
else if (loc == INSTAR) {
9904 for (i = 0; i < caveoldtetlist->objects; i++) {
9905 cavetet = (triface *) fastlookup(caveoldtetlist, i);
9907 for (j = 0; j < 4; j++) {
9908 decode(cavetet->tet[j], neightet);
9909 if (!infected(neightet)) {
9911 neightet.ver = epivot[neightet.ver];
9912 cavebdrylist->newindex((
void **) &parytet);
9913 *parytet = neightet;
9917 }
else if (loc == ONVERTEX) {
9923 if (ivf->assignmeshsize) {
9927 bgm->decode(point2bgmtet(org(*searchtet)), neightet);
9928 int bgmloc = (int) bgm->scoutpoint(insertpt, &neightet, 0);
9929 if (bgmloc != (
int) OUTSIDE) {
9930 insertpt[pointmtrindex] =
9931 bgm->getpointmeshsize(insertpt, &neightet, bgmloc);
9932 setpoint2bgmtet(insertpt, bgm->encode(neightet));
9935 insertpt[pointmtrindex] = getpointmeshsize(insertpt,searchtet,(
int)loc);
9941 swaplist = cavetetlist;
9942 cavetetlist = cavebdrylist;
9943 cavebdrylist = swaplist;
9944 for (i = 0; i < cavetetlist->objects; i++) {
9946 cavetet = (triface *) fastlookup(cavetetlist, i);
9948 if (!infected(*cavetet)) {
9953 if (!marktested(*cavetet)) {
9955 pts = (point *) cavetet->tet;
9956 if (pts[7] != dummypoint) {
9959 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], insertpt,
9960 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
9963 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], insertpt);
9965 enqflag = (sign < 0.0);
9969 ori = orient3d(pts[4], pts[5], pts[6], insertpt);
9974 }
else if (ori == 0.0) {
9978 decode(cavetet->tet[3], neineitet);
9979 if (!infected(neineitet)) {
9980 if (!marktested(neineitet)) {
9982 pts = (point *) neineitet.tet;
9984 sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt,
9985 pts[4][3], pts[5][3], pts[6][3],
9986 pts[7][3], insertpt[3]);
9988 sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt);
9990 enqflag = (sign < 0.0);
10004 decode(cavetet->tet[3], neineitet);
10005 if (!infected(neineitet)) {
10006 if (!marktested(neineitet)) {
10008 pts = (point *) neineitet.tet;
10010 sign = orient4d_s(pts[4],pts[5],pts[6],pts[7], insertpt,
10011 pts[4][3], pts[5][3], pts[6][3],
10012 pts[7][3], insertpt[3]);
10014 sign = insphere_s(pts[4],pts[5],pts[6],pts[7], insertpt);
10016 enqflag = (sign < 0.0);
10025 marktest(*cavetet);
10030 k = (cavetet->ver & 3);
10031 for (j = 1; j < 4; j++) {
10032 decode(cavetet->tet[(j + k) % 4], neightet);
10033 cavetetlist->newindex((
void **) &parytet);
10034 *parytet = neightet;
10037 caveoldtetlist->newindex((
void **) &parytet);
10038 *parytet = *cavetet;
10041 cavetet->ver = epivot[cavetet->ver];
10042 cavebdrylist->newindex((
void **) &parytet);
10043 *parytet = *cavetet;
10048 cavetetlist->restart();
10051 if (checksubsegflag) {
10054 for (i = 0; i < caveoldtetlist->objects; i++) {
10055 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10056 if ((ssptr = (shellface*) cavetet->tet[8]) != NULL) {
10057 for (j = 0; j < 6; j++) {
10059 sdecode(ssptr[j], checkseg);
10060 if (!sinfected(checkseg)) {
10062 cavetetseglist->newindex((
void **) &paryseg);
10063 *paryseg = checkseg;
10070 for (i = 0; i < cavetetseglist->objects; i++) {
10071 paryseg = (face *) fastlookup(cavetetseglist, i);
10072 suninfect(*paryseg);
10075 if (ivf->rejflag & 1) {
10078 for (i = 0; i < cavetetseglist->objects; i++) {
10079 paryseg1 = (face *) fastlookup(cavetetseglist, i);
10080 if (checkseg4encroach((point) paryseg1->sh[3], (point) paryseg1->sh[4],
10082 encseglist->newindex((
void **) &paryseg);
10083 *paryseg = *paryseg1;
10086 if ((ivf->rejflag & 1) && (encseglist->objects > 0)) {
10087 insertpoint_abort(splitseg, ivf);
10088 ivf->iloc = (int) ENCSEGMENT;
10094 if (checksubfaceflag) {
10097 for (i = 0; i < caveoldtetlist->objects; i++) {
10098 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10099 if ((sptr = (shellface*) cavetet->tet[9]) != NULL) {
10100 for (j = 0; j < 4; j++) {
10102 sdecode(sptr[j], checksh);
10103 if (!sinfected(checksh)) {
10105 cavetetshlist->newindex((
void **) &parysh);
10113 for (i = 0; i < cavetetshlist->objects; i++) {
10114 parysh = (face *) fastlookup(cavetetshlist, i);
10115 suninfect(*parysh);
10118 if (ivf->rejflag & 2) {
10122 for (i = 0; i < cavetetshlist->objects; i++) {
10123 parysh = (face *) fastlookup(cavetetshlist, i);
10124 if (checkfac4encroach((point) parysh->sh[3], (point) parysh->sh[4],
10125 (point) parysh->sh[5], insertpt, cent, &rd)) {
10126 encshlist->newindex((
void **) &bface);
10127 bface->ss = *parysh;
10128 bface->forg = (point) parysh->sh[3];
10129 for (j = 0; j < 3; j++) bface->cent[j] = cent[j];
10133 if (encshlist->objects > 0) {
10134 insertpoint_abort(splitseg, ivf);
10135 ivf->iloc = (int) ENCSUBFACE;
10141 if ((ivf->iloc == (
int) OUTSIDE) && ivf->refineflag) {
10144 insertpoint_abort(splitseg, ivf);
10148 if (ivf->splitbdflag) {
10153 for (i = 0; i < caveshlist->objects; i++) {
10154 parysh = (face *) fastlookup(caveshlist, i);
10156 for (j = 0; j < 3; j++) {
10157 if (!isshsubseg(checksh)) {
10158 spivot(checksh, neighsh);
10159 if (!smarktested(neighsh)) {
10160 stpivot(neighsh, neightet);
10161 if (infected(neightet)) {
10162 fsymself(neightet);
10163 if (infected(neightet)) {
10168 sign = incircle3d(sorg(neighsh), sdest(neighsh),
10169 sapex(neighsh), insertpt);
10171 smarktest(neighsh);
10172 caveshlist->newindex((
void **) &parysh);
10179 senextself(checksh);
10184 if (ivf->validflag) {
10188 if (ivf->respectbdflag) {
10193 for (i = 0; i < cavetetshlist->objects; i++) {
10194 parysh = (face *) fastlookup(cavetetshlist, i);
10195 stpivot(*parysh, neightet);
10196 if (infected(neightet)) {
10197 fsymself(neightet);
10198 if (infected(neightet)) {
10200 if (!smarktested(*parysh)) {
10204 if (oppo(neightet) != dummypoint) {
10205 fsymself(neightet);
10207 if (oppo(neightet) != dummypoint) {
10208 ori = orient3d(org(neightet), dest(neightet), apex(neightet),
10212 fsymself(neightet);
10221 uninfect(neightet);
10222 unmarktest(neightet);
10224 neightet.ver = epivot[neightet.ver];
10225 cavebdrylist->newindex((
void **) &parytet);
10226 *parytet = neightet;
10228 for (j = 0; j < 3; j++) {
10229 esym(neightet, neineitet);
10230 neineitet.ver = epivot[neineitet.ver];
10231 cavebdrylist->newindex((
void **) &parytet);
10232 *parytet = neineitet;
10233 enextself(neightet);
10244 for (i = 0; i < cavetetseglist->objects; i++) {
10245 paryseg = (face *) fastlookup(cavetetseglist, i);
10247 if (!smarktested(*paryseg)) {
10248 sstpivot1(*paryseg, neightet);
10249 spintet = neightet;
10251 if (!infected(spintet))
break;
10252 fnextself(spintet);
10253 if (spintet.tet == neightet.tet)
break;
10255 if (infected(spintet)) {
10258 pa = org(neightet);
10259 pb = dest(neightet);
10260 spintet = neightet;
10264 pc = apex(spintet);
10265 if (pc != dummypoint) {
10266 ori = orient3d(pa, pb, pc, insertpt);
10269 esym(spintet, neineitet);
10270 pc = apex(neineitet);
10271 if (pc != dummypoint) {
10272 ori = orient3d(pb, pa, pc, insertpt);
10281 fnextself(spintet);
10282 if (spintet.tet == neightet.tet)
break;
10286 terminatetetgen(
this, 2);
10288 neightet = spintet;
10289 if (b->verbose > 3) {
10290 printf(
" Cut tet (%d, %d, %d, %d)\n",
10291 pointmark(org(neightet)), pointmark(dest(neightet)),
10292 pointmark(apex(neightet)), pointmark(oppo(neightet)));
10294 uninfect(neightet);
10295 unmarktest(neightet);
10297 neightet.ver = epivot[neightet.ver];
10298 cavebdrylist->newindex((
void **) &parytet);
10299 *parytet = neightet;
10301 for (j = 0; j < 3; j++) {
10302 esym(neightet, neineitet);
10303 neineitet.ver = epivot[neineitet.ver];
10304 cavebdrylist->newindex((
void **) &parytet);
10305 *parytet = neineitet;
10306 enextself(neightet);
10314 for (i = 0; i < cavebdrylist->objects; i++) {
10315 cavetet = (triface *) fastlookup(cavebdrylist, i);
10318 fsym(*cavetet, neightet);
10319 if (infected(neightet)) {
10320 if (apex(*cavetet) != dummypoint) {
10322 if (oppo(neightet) != dummypoint) {
10324 if (issubface(neightet)) {
10327 pa = org(*cavetet);
10328 pb = dest(*cavetet);
10329 pc = apex(*cavetet);
10330 volume = orient3dfast(pa, pb, pc, insertpt);
10331 attrib = distance(pa, pb) * distance(pb, pc) * distance(pc, pa);
10332 if ((fabs(volume) / attrib) < b->epsilon) {
10335 ori = orient3d(pa, pb, pc, insertpt);
10338 ori = orient3d(org(*cavetet), dest(*cavetet), apex(*cavetet),
10341 enqflag = (ori > 0);
10354 cavetetlist->newindex((
void **) &parytet);
10355 *parytet = *cavetet;
10357 uninfect(neightet);
10358 unmarktest(neightet);
10361 for (j = 0; j < 3; j++) {
10362 esym(neightet, neineitet);
10363 neineitet.ver = epivot[neineitet.ver];
10364 cavebdrylist->newindex((
void **) &parytet);
10365 *parytet = neineitet;
10366 enextself(neightet);
10369 unmarktest(*cavetet);
10373 unmarktest(*cavetet);
10377 if (cutcount > 0) {
10380 cavebdrylist->restart();
10381 for (i = 0; i < cavetetlist->objects; i++) {
10382 cavetet = (triface *) fastlookup(cavetetlist, i);
10384 fsym(*cavetet, neightet);
10385 if (infected(neightet)) {
10387 cavebdrylist->newindex((
void **) &parytet);
10388 *parytet = *cavetet;
10391 unmarktest(*cavetet);
10396 cavetetlist->restart();
10397 for (i = 0; i < caveoldtetlist->objects; i++) {
10398 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10399 if (infected(*cavetet)) {
10400 cavetetlist->newindex((
void **) &parytet);
10401 *parytet = *cavetet;
10405 swaplist = caveoldtetlist;
10406 caveoldtetlist = cavetetlist;
10407 cavetetlist = swaplist;
10410 if (caveoldtetlist->objects == 0l) {
10411 insertpoint_abort(splitseg, ivf);
10412 ivf->iloc = (int) BADELEMENT;
10416 if (ivf->splitbdflag) {
10417 int cutshcount = 0;
10419 for (i = 0; i < caveshlist->objects; i++) {
10420 parysh = (face *) fastlookup(caveshlist, i);
10421 if (smarktested(*parysh)) {
10423 stpivot(*parysh, neightet);
10424 if (infected(neightet)) {
10425 fsymself(neightet);
10426 if (infected(neightet)) {
10431 sunmarktest(*parysh);
10433 j = caveshlist->objects - 1;
10434 checksh = * (face *) fastlookup(caveshlist, j);
10437 caveshlist->objects--;
10443 if (cutshcount > 0) {
10446 if (loc == ONFACE) {
10447 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
10449 if (!smarktested(*splitsh)) i++;
10451 }
else if (loc == ONEDGE) {
10452 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
10454 if (!smarktested(*splitseg)) i++;
10456 if ((splitsh != NULL) && (splitsh->sh != NULL)) {
10458 pa = sorg(*splitsh);
10459 neighsh = *splitsh;
10462 if (sorg(neighsh) != pa) {
10463 sesymself(neighsh);
10466 if (!smarktested(neighsh)) i++;
10468 spivotself(neighsh);
10470 if (neighsh.sh == splitsh->sh)
break;
10471 if (neighsh.sh == NULL)
break;
10478 insertpoint_abort(splitseg, ivf);
10479 ivf->iloc = (int) BADELEMENT;
10488 if (ivf->refineflag) {
10493 if (((ivf->refineflag == 1) && !infected(ivf->refinetet)) ||
10494 ((ivf->refineflag == 2) && !smarktested(ivf->refinesh))) {
10495 insertpoint_abort(splitseg, ivf);
10496 ivf->iloc = (int) BADELEMENT;
10501 if (b->plc && (loc != INSTAR)) {
10505 if (loc == OUTSIDE) {
10506 pts = (point *) &(searchtet->tet[4]);
10507 for (i = 0; i < 3; i++) {
10508 cavetetvertlist->newindex((
void **) &parypt);
10511 }
else if (loc == INTETRAHEDRON) {
10512 pts = (point *) &(searchtet->tet[4]);
10513 for (i = 0; i < 4; i++) {
10514 cavetetvertlist->newindex((
void **) &parypt);
10517 }
else if (loc == ONFACE) {
10518 pts = (point *) &(searchtet->tet[4]);
10519 for (i = 0; i < 3; i++) {
10520 cavetetvertlist->newindex((
void **) &parypt);
10523 if (pts[3] != dummypoint) {
10524 cavetetvertlist->newindex((
void **) &parypt);
10527 fsym(*searchtet, spintet);
10528 if (oppo(spintet) != dummypoint) {
10529 cavetetvertlist->newindex((
void **) &parypt);
10530 *parypt = oppo(spintet);
10532 }
else if (loc == ONEDGE) {
10533 spintet = *searchtet;
10534 cavetetvertlist->newindex((
void **) &parypt);
10535 *parypt = org(spintet);
10536 cavetetvertlist->newindex((
void **) &parypt);
10537 *parypt = dest(spintet);
10539 if (apex(spintet) != dummypoint) {
10540 cavetetvertlist->newindex((
void **) &parypt);
10541 *parypt = apex(spintet);
10543 fnextself(spintet);
10544 if (spintet.tet == searchtet->tet)
break;
10548 int rejptflag = (ivf->rejflag & 4);
10552 for (i = 0; i < cavetetvertlist->objects; i++) {
10553 parypt = (point *) fastlookup(cavetetvertlist, i);
10554 rd = distance(*parypt, insertpt);
10556 if (rd < minedgelength) {
10563 if (rd < (0.5 * (*parypt)[pointmtrindex])) {
10570 cavetetvertlist->restart();
10575 if (loc == NEARVERTEX) {
10576 if (!issteinerpoint(insertpt) && b->nomergevertex) {
10580 printf(
"Warning: Two points, %d and %d, are very close.\n",
10581 pointmark(insertpt), pointmark(*pts));
10582 printf(
" Creating a very short edge (len = %g) (< %g).\n",
10583 rd, minedgelength);
10584 printf(
" You may try a smaller tolerance (-T) (current is %g)\n",
10586 printf(
" to avoid this warning.\n");
10589 point2tetorg(*pts, *searchtet);
10590 insertpoint_abort(splitseg, ivf);
10591 ivf->iloc = (int) loc;
10596 point2tetorg(*pts, *searchtet);
10597 insertpoint_abort(splitseg, ivf);
10598 ivf->iloc = (int) loc;
10604 if (b->weighted || ivf->cdtflag || ivf->smlenflag
10608 for (i = 0; i < caveoldtetlist->objects; i++) {
10609 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10611 pts = (point *) &(cavetet->tet[4]);
10612 for (j = 0; j < 4; j++) {
10613 if (pts[j] != dummypoint) {
10614 if (!pinfected(pts[j])) {
10616 cavetetvertlist->newindex((
void **) &parypt);
10623 for (i = 0; i < cavetetvertlist->objects; i++) {
10624 parypt = (point *) fastlookup(cavetetvertlist, i);
10625 puninfect(*parypt);
10627 if (ivf->smlenflag) {
10630 parypt = (point *) fastlookup(cavetetvertlist, 0);
10631 ivf->smlen = distance(*parypt, insertpt);
10632 ivf->parentpt = *parypt;
10633 for (i = 1; i < cavetetvertlist->objects; i++) {
10634 parypt = (point *) fastlookup(cavetetvertlist, i);
10635 len = distance(*parypt, insertpt);
10636 if (len < ivf->smlen) {
10638 ivf->parentpt = *parypt;
10645 if (ivf->cdtflag) {
10647 for (i = 0; i < caveoldtetlist->objects; i++) {
10648 cavetet = (triface *) fastlookup(caveoldtetlist, i);
10649 unmarktest(*cavetet);
10651 for (i = 0; i < cavebdrylist->objects; i++) {
10652 cavetet = (triface *) fastlookup(cavebdrylist, i);
10653 unmarktest(*cavetet);
10656 cavetetlist->restart();
10657 if (checksubsegflag) {
10658 cavetetseglist->restart();
10660 if (checksubfaceflag) {
10661 cavetetshlist->restart();
10671 if (checksubsegflag) {
10672 for (i = 0; i < cavetetseglist->objects; i++) {
10673 paryseg = (face *) fastlookup(cavetetseglist, i);
10675 if (!smarktested(*paryseg)) {
10680 sstpivot1(*paryseg, neightet);
10681 spintet = neightet;
10684 if (!infected(spintet)) {
10685 neineitet = spintet;
10689 fnextself(spintet);
10690 if (spintet.tet == neightet.tet)
break;
10696 s = cavetetseglist->objects - 1;
10697 checkseg = * (face *) fastlookup(cavetetseglist, s);
10698 *paryseg = checkseg;
10699 cavetetseglist->objects--;
10701 }
else if (k < j) {
10703 sstbond1(*paryseg, neineitet);
10706 if (!ivf->splitbdflag) {
10707 checkseg = *paryseg;
10709 caveencseglist->newindex((
void **) &paryseg);
10710 *paryseg = checkseg;
10713 terminatetetgen(
this, 2);
10725 if (checksubfaceflag) {
10726 for (i = 0; i < cavetetshlist->objects; i++) {
10727 parysh = (face *) fastlookup(cavetetshlist, i);
10729 if (!smarktested(*parysh)) {
10732 for (j = 0; j < 2; j++) {
10733 stpivot(*parysh, neightet);
10734 if (!infected(neightet)) {
10739 sesymself(*parysh);
10743 s = cavetetshlist->objects - 1;
10744 checksh = * (face *) fastlookup(cavetetshlist, s);
10746 cavetetshlist->objects--;
10748 }
else if (k == 1) {
10752 if (!ivf->splitbdflag) {
10755 caveencshlist->newindex((
void **) &parysh);
10759 terminatetetgen(
this, 2);
10773 for (i = 0; i < cavebdrylist->objects; i++) {
10774 cavetet = (triface *) fastlookup(cavebdrylist, i);
10775 neightet = *cavetet;
10776 unmarktest(neightet);
10778 fsym(neightet, oldtet);
10779 if (apex(neightet) != dummypoint) {
10781 maketetrahedron(&newtet);
10782 setorg(newtet, dest(neightet));
10783 setdest(newtet, org(neightet));
10784 setapex(newtet, apex(neightet));
10785 setoppo(newtet, insertpt);
10789 maketetrahedron(&newtet);
10790 setorg(newtet, org(neightet));
10791 setdest(newtet, dest(neightet));
10792 setapex(newtet, insertpt);
10793 setoppo(newtet, dummypoint);
10798 for (j = 0; j < numelemattrib; j++) {
10799 attrib = elemattribute(oldtet.tet, j);
10800 setelemattribute(newtet.tet, j, attrib);
10802 if (b->varvolume) {
10803 volume = volumebound(oldtet.tet);
10804 setvolumebound(newtet.tet, volume);
10807 bond(newtet, neightet);
10813 recenttet = newtet;
10815 setpoint2tet(insertpt, (tetrahedron) (newtet.tet));
10818 cavetetlist->restart();
10821 for (i = 0; i < cavebdrylist->objects; i++) {
10822 cavetet = (triface *) fastlookup(cavebdrylist, i);
10825 fsym(oldtet, neightet);
10826 fsym(neightet, newtet);
10829 for (j = 0; j < 3; j++) {
10830 esym(newtet, neightet);
10831 if (neightet.tet[neightet.ver & 3] == NULL) {
10835 fnextself(spintet);
10836 if (!infected(spintet))
break;
10838 fsym(spintet, newneitet);
10839 esymself(newneitet);
10840 bond(neightet, newneitet);
10841 if (ivf->lawson > 1) {
10842 cavetetlist->newindex((
void **) &parytet);
10843 *parytet = neightet;
10847 setpoint2tet(org(newtet), (tetrahedron) (newtet.tet));
10854 if (checksubfaceflag) {
10856 for (i = 0; i < cavetetshlist->objects; i++) {
10857 parysh = (face *) fastlookup(cavetetshlist, i);
10859 if (!sinfected(*parysh)) {
10860 stpivot(*parysh, neightet);
10861 fsym(neightet, spintet);
10862 sesymself(*parysh);
10863 tsbond(spintet, *parysh);
10868 if (checksubsegflag) {
10870 for (i = 0; i < cavetetseglist->objects; i++) {
10871 paryseg = (face *) fastlookup(cavetetseglist, i);
10873 if (!sinfected(*paryseg)) {
10874 sstpivot1(*paryseg, neightet);
10875 spintet = neightet;
10877 tssbond1(spintet, *paryseg);
10878 fnextself(spintet);
10879 if (spintet.tet == neightet.tet)
break;
10885 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
10886 ((splitseg != NULL) && (splitseg->sh != NULL))) {
10888 sinsertvertex(insertpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0);
10891 if (checksubfaceflag) {
10892 if (ivf->splitbdflag) {
10894 for (i = 0; i < caveshbdlist->objects; i++) {
10896 parysh = (face *) fastlookup(caveshbdlist, i);
10897 spivot(*parysh, checksh);
10899 if (checksh.sh[3] != NULL) {
10902 stpivot(*parysh, neightet);
10904 spintet = neightet;
10906 fnextself(spintet);
10907 if (!infected(spintet))
break;
10910 fsym(spintet, neightet);
10912 spintet = neightet;
10914 fnextself(spintet);
10915 if (apex(spintet) == insertpt)
break;
10918 if (sorg(checksh) != org(spintet)) {
10919 sesymself(checksh);
10922 tsbond(spintet, checksh);
10924 sesymself(checksh);
10925 tsbond(spintet, checksh);
10931 for (i = 0; i < caveshbdlist->objects; i++) {
10933 parysh = (face *) fastlookup(caveshbdlist, i);
10934 spivot(*parysh, checksh);
10936 if (checksh.sh[3] != NULL) {
10937 subfacstack->newindex((
void **) &parysh);
10942 for (i = 0; i < caveencshlist->objects; i++) {
10943 parysh = (face *) fastlookup(caveencshlist, i);
10946 if (!smarktested(*parysh)) {
10948 suninfect(checksh);
10949 stdissolve(checksh);
10950 subfacstack->newindex((
void **) &parysh);
10957 if (checksubsegflag) {
10958 if (ivf->splitbdflag) {
10959 if (splitseg != NULL) {
10961 for (i = 0; i < cavesegshlist->objects; i++) {
10962 paryseg = (face *) fastlookup(cavesegshlist, i);
10964 checkseg = *paryseg;
10966 checkseg.shver = 0;
10967 spivot(checkseg, checksh);
10968 if (checksh.sh != NULL) {
10970 stpivot(checksh, neightet);
10973 point2tetorg(sorg(checkseg), neightet);
10974 finddirection(&neightet, sdest(checkseg));
10976 sstbond1(checkseg, neightet);
10977 spintet = neightet;
10979 tssbond1(spintet, checkseg);
10980 fnextself(spintet);
10981 if (spintet.tet == neightet.tet)
break;
10988 if (splitseg != NULL) {
10990 for (i = 0; i < cavesegshlist->objects; i++) {
10991 paryseg = (face *) fastlookup(cavesegshlist, i);
10992 checkseg = *paryseg;
10994 s = randomnation(subsegstack->objects + 1);
10995 subsegstack->newindex((
void **) &paryseg);
10996 *paryseg = * (face *) fastlookup(subsegstack, s);
10997 paryseg = (face *) fastlookup(subsegstack, s);
10998 *paryseg = checkseg;
11001 for (i = 0; i < caveencseglist->objects; i++) {
11002 paryseg = (face *) fastlookup(caveencseglist, i);
11003 if (!smarktested(*paryseg)) {
11004 checkseg = *paryseg;
11005 suninfect(checkseg);
11006 sstdissolve1(checkseg);
11007 s = randomnation(subsegstack->objects + 1);
11008 subsegstack->newindex((
void **) &paryseg);
11009 *paryseg = * (face *) fastlookup(subsegstack, s);
11010 paryseg = (face *) fastlookup(subsegstack, s);
11011 *paryseg = checkseg;
11023 for (i = 0; i < cavetetvertlist->objects; i++) {
11024 pts = (point *) fastlookup(cavetetvertlist, i);
11025 decode(point2tet(*pts), *searchtet);
11026 if (infected(*searchtet)) {
11028 if (b->verbose > 1) {
11029 printf(
" Point #%d is non-regular after the insertion of #%d.\n",
11030 pointmark(*pts), pointmark(insertpt));
11032 setpointtype(*pts, NREGULARVERTEX);
11039 if (ivf->chkencflag & 1) {
11041 for (i = 0; i < cavetetseglist->objects; i++) {
11042 paryseg = (face *) fastlookup(cavetetseglist, i);
11044 if (!sinfected(*paryseg)) {
11045 enqueuesubface(badsubsegs, paryseg);
11048 if (splitseg != NULL) {
11050 for (i = 0; i < cavesegshlist->objects; i++) {
11051 paryseg = (face *) fastlookup(cavesegshlist, i);
11052 enqueuesubface(badsubsegs, paryseg);
11057 if (ivf->chkencflag & 2) {
11059 for (i = 0; i < cavetetshlist->objects; i++) {
11060 parysh = (face *) fastlookup(cavetetshlist, i);
11062 if (!sinfected(*parysh)) {
11063 enqueuesubface(badsubfacs, parysh);
11067 for (i = 0; i < caveshbdlist->objects; i++) {
11069 parysh = (face *) fastlookup(caveshbdlist, i);
11070 spivot(*parysh, checksh);
11072 if (checksh.sh[3] != NULL) {
11073 enqueuesubface(badsubfacs, &checksh);
11078 if (ivf->chkencflag & 4) {
11080 for (i = 0; i < cavebdrylist->objects; i++) {
11081 cavetet = (triface *) fastlookup(cavebdrylist, i);
11082 enqueuetetrahedron(cavetet);
11089 for (i = 0; i < caveoldtetlist->objects; i++) {
11090 searchtet = (triface *) fastlookup(caveoldtetlist, i);
11091 if (ishulltet(*searchtet)) {
11094 tetrahedrondealloc(searchtet->tet);
11097 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
11098 ((splitseg != NULL) && (splitseg->sh != NULL))) {
11100 for (i = 0; i < caveshlist->objects; i++) {
11101 parysh = (face *) fastlookup(caveshlist, i);
11102 if (checksubfaceflag) {
11106 stpivot(*parysh, neightet);
11107 if (neightet.tet != NULL) {
11108 if (neightet.tet[4] != NULL) {
11110 tsdissolve(neightet);
11111 fsymself(neightet);
11112 tsdissolve(neightet);
11116 shellfacedealloc(subfaces, parysh->sh);
11118 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
11120 shellfacedealloc(subsegs, splitseg->sh);
11125 for (i = 0; i < cavebdrylist->objects; i++) {
11126 searchtet = (triface *) fastlookup(cavebdrylist, i);
11127 flippush(flipstack, searchtet);
11129 if (ivf->lawson > 1) {
11130 for (i = 0; i < cavetetlist->objects; i++) {
11131 searchtet = (triface *) fastlookup(cavetetlist, i);
11132 flippush(flipstack, searchtet);
11140 caveoldtetlist->restart();
11141 cavebdrylist->restart();
11142 cavetetlist->restart();
11144 if (checksubsegflag) {
11145 cavetetseglist->restart();
11146 caveencseglist->restart();
11149 if (checksubfaceflag) {
11150 cavetetshlist->restart();
11151 caveencshlist->restart();
11154 if (b->weighted || ivf->smlenflag
11156 cavetetvertlist->restart();
11159 if (((splitsh != NULL) && (splitsh->sh != NULL)) ||
11160 ((splitseg != NULL) && (splitseg->sh != NULL))) {
11161 caveshlist->restart();
11162 caveshbdlist->restart();
11163 cavesegshlist->restart();
11177 void tetgenmesh::insertpoint_abort(face *splitseg, insertvertexflags *ivf)
11183 for (i = 0; i < caveoldtetlist->objects; i++) {
11184 cavetet = (triface *) fastlookup(caveoldtetlist, i);
11185 uninfect(*cavetet);
11186 unmarktest(*cavetet);
11188 for (i = 0; i < cavebdrylist->objects; i++) {
11189 cavetet = (triface *) fastlookup(cavebdrylist, i);
11190 unmarktest(*cavetet);
11192 cavetetlist->restart();
11193 cavebdrylist->restart();
11194 caveoldtetlist->restart();
11195 cavetetseglist->restart();
11196 cavetetshlist->restart();
11197 if (ivf->splitbdflag) {
11198 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
11199 sunmarktest(*splitseg);
11201 for (i = 0; i < caveshlist->objects; i++) {
11202 parysh = (face *) fastlookup(caveshlist, i);
11203 sunmarktest(*parysh);
11205 caveshlist->restart();
11206 cavesegshlist->restart();
11229 void tetgenmesh::transfernodes()
11242 for (i = 0; i < in->numberofpoints; i++) {
11243 makepoint(&pointloop, UNUSEDVERTEX);
11245 x = pointloop[0] = in->pointlist[coordindex++];
11246 y = pointloop[1] = in->pointlist[coordindex++];
11247 z = pointloop[2] = in->pointlist[coordindex++];
11249 for (j = 0; j < in->numberofpointattributes; j++) {
11250 pointloop[3 + j] = in->pointattributelist[attribindex++];
11253 for (j = 0; j < in->numberofpointmtrs; j++) {
11254 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
11257 if (in->numberofpointattributes > 0) {
11265 if (w < fabs(y)) w = fabs(y);
11266 if (w < fabs(z)) w = fabs(z);
11268 if (b->weighted_param == 0) {
11269 pointloop[3] = x * x + y * y + z * z - w;
11280 xmin = (x < xmin) ? x : xmin;
11281 xmax = (x > xmax) ? x : xmax;
11282 ymin = (y < ymin) ? y : ymin;
11283 ymax = (y > ymax) ? y : ymax;
11284 zmin = (z < zmin) ? z : zmin;
11285 zmax = (z > zmax) ? z : zmax;
11289 setpointgeomuv(pointloop, 0, in->pointparamlist[i].uv[0]);
11290 setpointgeomuv(pointloop, 1, in->pointparamlist[i].uv[1]);
11291 setpointgeomtag(pointloop, in->pointparamlist[i].tag);
11292 if (in->pointparamlist[i].type == 0) {
11293 setpointtype(pointloop, RIDGEVERTEX);
11294 }
else if (in->pointparamlist[i].type == 1) {
11295 setpointtype(pointloop, FREESEGVERTEX);
11296 }
else if (in->pointparamlist[i].type == 2) {
11297 setpointtype(pointloop, FREEFACETVERTEX);
11298 }
else if (in->pointparamlist[i].type == 3) {
11299 setpointtype(pointloop, FREEVOLVERTEX);
11308 longest = sqrt(x * x + y * y + z * z);
11309 if (longest == 0.0) {
11310 printf(
"Error: The point set is trivial.\n");
11311 terminatetetgen(
this, 10);
11314 minedgelength = longest * b->epsilon;
11333 void tetgenmesh::hilbert_init(
int n)
11335 int gc[8], N, mask, travel_bit;
11340 N = (n == 2) ? 4 : 8;
11341 mask = (n == 2) ? 3 : 7;
11344 for (i = 0; i < N; i++) {
11345 gc[i] = i ^ (i >> 1);
11348 for (e = 0; e < N; e++) {
11349 for (d = 0; d < n; d++) {
11353 travel_bit = e ^ f;
11354 for (i = 0; i < N; i++) {
11356 k = gc[i] * (travel_bit * 2);
11357 g = ((k | (k / N)) & mask);
11359 transgc[e][d][i] = (g ^ e);
11366 for (i = 1; i < N; i++) {
11368 v = (v ^ (v - 1)) >> 1;
11369 for (c = 0; v; c++) {
11372 tsb1mod3[i] = c % n;
11382 int tetgenmesh::hilbert_split(point* vertexarray,
int arraysize,
int gc0,
int gc1,
11383 REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
11384 REAL bzmin, REAL bzmax)
11394 axis = (gc0 ^ gc1) >> 1;
11398 split = 0.5 * (bxmin + bxmax);
11399 }
else if (axis == 1) {
11400 split = 0.5 * (bymin + bymax);
11402 split = 0.5 * (bzmin + bzmax);
11407 d = ((gc0 & (1<<axis)) == 0) ? 1 : -1;
11418 for (; i < arraysize; i++) {
11419 if (vertexarray[i][axis] >= split)
break;
11421 for (; j >= 0; j--) {
11422 if (vertexarray[j][axis] < split)
break;
11425 if (i == (j + 1))
break;
11427 swapvert = vertexarray[i];
11428 vertexarray[i] = vertexarray[j];
11429 vertexarray[j] = swapvert;
11434 for (; i < arraysize; i++) {
11435 if (vertexarray[i][axis] <= split)
break;
11437 for (; j >= 0; j--) {
11438 if (vertexarray[j][axis] > split)
break;
11441 if (i == (j + 1))
break;
11443 swapvert = vertexarray[i];
11444 vertexarray[i] = vertexarray[j];
11445 vertexarray[j] = swapvert;
11453 void tetgenmesh::hilbert_sort3(point* vertexarray,
int arraysize,
int e,
int d,
11454 REAL bxmin, REAL bxmax, REAL bymin, REAL bymax,
11455 REAL bzmin, REAL bzmax,
int depth)
11457 REAL x1, x2, y1, y2, z1, z2;
11458 int p[9], w, e_w, d_w, k, ei, di;
11459 int n = 3, mask = 7;
11465 p[4] = hilbert_split(vertexarray, p[8], transgc[e][d][3], transgc[e][d][4],
11466 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11467 p[2] = hilbert_split(vertexarray, p[4], transgc[e][d][1], transgc[e][d][2],
11468 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11469 p[1] = hilbert_split(vertexarray, p[2], transgc[e][d][0], transgc[e][d][1],
11470 bxmin, bxmax, bymin, bymax, bzmin, bzmax);
11471 p[3] = hilbert_split(&(vertexarray[p[2]]), p[4] - p[2],
11472 transgc[e][d][2], transgc[e][d][3],
11473 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[2];
11474 p[6] = hilbert_split(&(vertexarray[p[4]]), p[8] - p[4],
11475 transgc[e][d][5], transgc[e][d][6],
11476 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
11477 p[5] = hilbert_split(&(vertexarray[p[4]]), p[6] - p[4],
11478 transgc[e][d][4], transgc[e][d][5],
11479 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[4];
11480 p[7] = hilbert_split(&(vertexarray[p[6]]), p[8] - p[6],
11481 transgc[e][d][6], transgc[e][d][7],
11482 bxmin, bxmax, bymin, bymax, bzmin, bzmax) + p[6];
11484 if (b->hilbert_order > 0) {
11486 if ((depth + 1) == b->hilbert_order) {
11493 for (w = 0; w < 8; w++) {
11498 if ((p[w+1] - p[w]) > b->hilbert_limit) {
11505 k = 2 * ((w - 1) / 2);
11506 e_w = k ^ (k >> 1);
11509 e_w = ((k << (d+1)) & mask) | ((k >> (n-d-1)) & mask);
11516 d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w];
11518 di = (d + d_w + 1) % n;
11520 if (transgc[e][d][w] & 1) {
11521 x1 = 0.5 * (bxmin + bxmax);
11525 x2 = 0.5 * (bxmin + bxmax);
11527 if (transgc[e][d][w] & 2) {
11528 y1 = 0.5 * (bymin + bymax);
11532 y2 = 0.5 * (bymin + bymax);
11534 if (transgc[e][d][w] & 4) {
11535 z1 = 0.5 * (bzmin + bzmax);
11539 z2 = 0.5 * (bzmin + bzmax);
11541 hilbert_sort3(&(vertexarray[p[w]]), p[w+1] - p[w], ei, di,
11542 x1, x2, y1, y2, z1, z2, depth+1);
11553 void tetgenmesh::brio_multiscale_sort(point* vertexarray,
int arraysize,
11554 int threshold, REAL ratio,
int *depth)
11559 if (arraysize >= threshold) {
11561 middle = arraysize * ratio;
11562 brio_multiscale_sort(vertexarray, middle, threshold, ratio, depth);
11565 hilbert_sort3(&(vertexarray[middle]), arraysize - middle, 0, 0,
11566 xmin, xmax, ymin, ymax, zmin, zmax, 0);
11575 unsigned long tetgenmesh::randomnation(
unsigned int choices)
11577 unsigned long newrandom;
11579 if (choices >= 714025l) {
11580 newrandom = (randomseed * 1366l + 150889l) % 714025l;
11581 randomseed = (newrandom * 1366l + 150889l) % 714025l;
11582 newrandom = newrandom * (choices / 714025l) + randomseed;
11583 if (newrandom >= choices) {
11584 return newrandom - choices;
11589 randomseed = (randomseed * 1366l + 150889l) % 714025l;
11590 return randomseed % choices;
11605 void tetgenmesh::randomsample(point searchpt,triface *searchtet)
11607 tetrahedron *firsttet, *tetptr;
11609 void **sampleblock;
11610 uintptr_t alignptr;
11611 long sampleblocks, samplesperblock, samplenum;
11612 long tetblocks, i, j;
11613 REAL searchdist, dist;
11615 if (b->verbose > 2) {
11616 printf(
" Random sampling tetrahedra for searching point %d.\n",
11617 pointmark(searchpt));
11621 if (searchtet->tet == NULL) {
11623 *searchtet = recenttet;
11628 searchtet->ver = 3;
11630 torg = org(*searchtet);
11631 searchdist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11632 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11633 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11637 if (recenttet.tet != searchtet->tet) {
11639 torg = org(recenttet);
11640 dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11641 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11642 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11643 if (dist < searchdist) {
11644 *searchtet = recenttet;
11650 searchdist = longest;
11656 while (samples * samples * samples * samples < tetrahedrons->items) {
11660 tetblocks = (tetrahedrons->maxitems + b->tetrahedraperblock - 1)
11661 / b->tetrahedraperblock;
11663 samplesperblock = 1 + (samples / tetblocks);
11664 sampleblocks = samples / samplesperblock;
11665 sampleblock = tetrahedrons->firstblock;
11666 for (i = 0; i < sampleblocks; i++) {
11667 alignptr = (uintptr_t) (sampleblock + 1);
11668 firsttet = (tetrahedron *)
11669 (alignptr + (uintptr_t) tetrahedrons->alignbytes
11670 - (alignptr % (uintptr_t) tetrahedrons->alignbytes));
11671 for (j = 0; j < samplesperblock; j++) {
11672 if (i == tetblocks - 1) {
11674 samplenum = randomnation((
int)
11675 (tetrahedrons->maxitems - (i * b->tetrahedraperblock)));
11677 samplenum = randomnation(b->tetrahedraperblock);
11679 tetptr = (tetrahedron *)
11680 (firsttet + (samplenum * tetrahedrons->itemwords));
11681 torg = (point) tetptr[4];
11682 if (torg != (point) NULL) {
11683 dist = (searchpt[0] - torg[0]) * (searchpt[0] - torg[0]) +
11684 (searchpt[1] - torg[1]) * (searchpt[1] - torg[1]) +
11685 (searchpt[2] - torg[2]) * (searchpt[2] - torg[2]);
11686 if (dist < searchdist) {
11687 searchtet->tet = tetptr;
11688 searchtet->ver = 11;
11693 if (i != tetblocks - 1) j--;
11696 sampleblock = (
void **) *sampleblock;
11722 enum tetgenmesh::locateresult
11723 tetgenmesh::locate(point searchpt, triface* searchtet,
int chkencflag)
11725 point torg, tdest, tapex, toppo;
11726 enum {ORGMOVE, DESTMOVE, APEXMOVE} nextmove;
11727 REAL ori, oriorg, oridest, oriapex;
11728 enum locateresult loc = OUTSIDE;
11732 torg = tdest = tapex = toppo = NULL;
11734 if (searchtet->tet == NULL) {
11736 searchtet->tet = recenttet.tet;
11740 if (ishulltet(*searchtet)) {
11742 searchtet->ver = 3;
11743 fsymself(*searchtet);
11747 for (searchtet->ver = 0; searchtet->ver < 4; searchtet->ver++) {
11748 torg = org(*searchtet);
11749 tdest = dest(*searchtet);
11750 tapex = apex(*searchtet);
11751 ori = orient3d(torg, tdest, tapex, searchpt);
11752 if (ori < 0.0)
break;
11754 if (searchtet->ver == 4) {
11755 terminatetetgen(
this, 2);
11761 toppo = oppo(*searchtet);
11764 if (toppo == searchpt) {
11766 esymself(*searchtet);
11767 eprevself(*searchtet);
11773 oriorg = orient3d(tdest, tapex, toppo, searchpt);
11774 oridest = orient3d(tapex, torg, toppo, searchpt);
11775 oriapex = orient3d(torg, tdest, toppo, searchpt);
11783 s = randomnation(3);
11785 nextmove = ORGMOVE;
11786 }
else if (s == 1) {
11787 nextmove = DESTMOVE;
11789 nextmove = APEXMOVE;
11794 if (randomnation(2)) {
11795 nextmove = ORGMOVE;
11797 nextmove = DESTMOVE;
11804 if (randomnation(2)) {
11805 nextmove = ORGMOVE;
11807 nextmove = APEXMOVE;
11811 nextmove = ORGMOVE;
11819 if (randomnation(2)) {
11820 nextmove = DESTMOVE;
11822 nextmove = APEXMOVE;
11826 nextmove = DESTMOVE;
11831 nextmove = APEXMOVE;
11837 enextesymself(*searchtet);
11838 if (oridest == 0) {
11839 eprevself(*searchtet);
11840 if (oriapex == 0) {
11848 if (oriapex == 0) {
11849 enextself(*searchtet);
11856 if (oridest == 0) {
11858 eprevesymself(*searchtet);
11859 if (oriapex == 0) {
11860 eprevself(*searchtet);
11867 if (oriapex == 0) {
11869 esymself(*searchtet);
11873 loc = INTETRAHEDRON;
11880 if (nextmove == ORGMOVE) {
11881 enextesymself(*searchtet);
11882 }
else if (nextmove == DESTMOVE) {
11883 eprevesymself(*searchtet);
11885 esymself(*searchtet);
11889 if (issubface(*searchtet)) {
11895 fsymself(*searchtet);
11896 if (oppo(*searchtet) == dummypoint) {
11902 torg = org(*searchtet);
11903 tdest = dest(*searchtet);
11904 tapex = apex(*searchtet);
11920 void tetgenmesh::flippush(badface*& fstack, triface* flipface)
11922 if (!facemarked(*flipface)) {
11923 badface *newflipface = (badface *) flippool->alloc();
11924 newflipface->tt = *flipface;
11925 markface(newflipface->tt);
11927 newflipface->nextitem = fstack;
11928 fstack = newflipface;
11951 int tetgenmesh::incrementalflip(point newpt,
int hullflag, flipconstraints *fc)
11954 triface fliptets[5], *parytet;
11955 point *pts, *parypt, pe;
11961 if (b->verbose > 2) {
11962 printf(
" Lawson flip (%ld faces).\n", flippool->items);
11968 popface = flipstack;
11969 while (popface != NULL) {
11970 pts = (point *) popface->tt.tet;
11971 for (i = 4; i < 8; i++) {
11972 if ((pts[i] != newpt) && (pts[i] != dummypoint)) {
11973 if (!pinfected(pts[i])) {
11975 cavetetvertlist->newindex((
void **) &parypt);
11980 popface = popface->nextitem;
11985 while (flipstack != NULL) {
11988 popface = flipstack;
11989 fliptets[0] = popface->tt;
11990 flipstack = flipstack->nextitem;
11991 flippool->dealloc((
void *) popface);
11994 if (isdeadtet(fliptets[0]))
continue;
11996 if (!facemarked(fliptets[0]))
continue;
11998 unmarkface(fliptets[0]);
12000 if ((point) fliptets[0].tet[7] == dummypoint) {
12002 fliptets[0].ver = epivot[fliptets[0].ver];
12004 fsym(fliptets[0], fliptets[1]);
12005 pts = (point *) fliptets[1].tet;
12006 ori = orient3d(pts[4], pts[5], pts[6], newpt);
12011 enext(fliptets[1], fliptets[2]);
12012 eprev(fliptets[1], fliptets[3]);
12013 fnextself(fliptets[2]);
12014 fnextself(fliptets[3]);
12015 if (oppo(fliptets[2]) == newpt) {
12016 if (oppo(fliptets[3]) == newpt) {
12018 terminatetetgen(
this, 2);
12020 esym(fliptets[2], fliptets[0]);
12021 fnext(fliptets[0], fliptets[1]);
12022 fnext(fliptets[1], fliptets[2]);
12029 flip32(fliptets, 1, fc);
12032 if (oppo(fliptets[3]) == newpt) {
12033 fnext(fliptets[3], fliptets[0]);
12034 fnext(fliptets[0], fliptets[1]);
12035 fnext(fliptets[1], fliptets[2]);
12040 flip32(fliptets, 1, fc);
12044 pe = oppo(fliptets[1]);
12045 if (!pinfected(pe)) {
12047 cavetetvertlist->newindex((
void **) &parypt);
12050 flip23(fliptets, 1, fc);
12059 flip23(fliptets, 1, fc);
12068 fsym(fliptets[0], fliptets[1]);
12069 if ((point) fliptets[1].tet[7] == dummypoint) {
12074 if (marktested(fliptets[1])) {
12080 pts = (point *) fliptets[1].tet;
12082 sign = orient4d_s(pts[4], pts[5], pts[6], pts[7], newpt,
12083 pts[4][3], pts[5][3], pts[6][3], pts[7][3],
12086 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], newpt);
12092 point pe = oppo(fliptets[1]);
12096 for (i = 0; i < 3; i++) {
12097 ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe);
12098 if (ori <= 0)
break;
12099 enextself(fliptets[0]);
12105 flip23(fliptets, 0, fc);
12111 esymself(fliptets[0]);
12112 for (i = 0; i < 3; i++) {
12113 fnext(fliptets[i], fliptets[i+1]);
12115 if (fliptets[3].tet == fliptets[0].tet) {
12117 flip32(fliptets, 0, fc);
12121 fnext(fliptets[3], fliptets[4]);
12122 if (fliptets[4].tet == fliptets[0].tet) {
12130 esymself(fliptets[0]);
12134 flip23(fliptets, 0, fc);
12135 fnext(fliptets[3], fliptets[1]);
12136 fnext(fliptets[1], fliptets[2]);
12144 flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc);
12152 marktest(fliptets[1]);
12154 cavebdrylist->newindex((
void **) &parytet);
12155 *parytet = fliptets[1];
12161 for (i = 0; i < cavebdrylist->objects; i++) {
12162 parytet = (triface *) fastlookup(cavebdrylist, i);
12163 unmarktest(*parytet);
12165 cavebdrylist->restart();
12169 for (i = 0; i < cavetetvertlist->objects; i++) {
12170 parypt = (point *) fastlookup(cavetetvertlist, i);
12171 puninfect(*parypt);
12173 cavetetvertlist->restart();
12189 void tetgenmesh::initialdelaunay(point pa, point pb, point pc, point pd)
12191 triface firsttet, tetopa, tetopb, tetopc, tetopd;
12192 triface worktet, worktet1;
12194 if (b->verbose > 2) {
12195 printf(
" Create init tet (%d, %d, %d, %d)\n", pointmark(pa),
12196 pointmark(pb), pointmark(pc), pointmark(pd));
12200 maketetrahedron(&firsttet);
12201 setvertices(firsttet, pa, pb, pc, pd);
12203 maketetrahedron(&tetopa);
12204 setvertices(tetopa, pb, pc, pd, dummypoint);
12205 maketetrahedron(&tetopb);
12206 setvertices(tetopb, pc, pa, pd, dummypoint);
12207 maketetrahedron(&tetopc);
12208 setvertices(tetopc, pa, pb, pd, dummypoint);
12209 maketetrahedron(&tetopd);
12210 setvertices(tetopd, pb, pa, pc, dummypoint);
12214 bond(firsttet, tetopd);
12215 esym(firsttet, worktet);
12216 bond(worktet, tetopc);
12217 enextesym(firsttet, worktet);
12218 bond(worktet, tetopa);
12219 eprevesym(firsttet, worktet);
12220 bond(worktet, tetopb);
12223 esym(tetopc, worktet);
12224 esym(tetopd, worktet1);
12225 bond(worktet, worktet1);
12226 esym(tetopa, worktet);
12227 eprevesym(tetopd, worktet1);
12228 bond(worktet, worktet1);
12229 esym(tetopb, worktet);
12230 enextesym(tetopd, worktet1);
12231 bond(worktet, worktet1);
12232 eprevesym(tetopc, worktet);
12233 enextesym(tetopb, worktet1);
12234 bond(worktet, worktet1);
12235 eprevesym(tetopa, worktet);
12236 enextesym(tetopc, worktet1);
12237 bond(worktet, worktet1);
12238 eprevesym(tetopb, worktet);
12239 enextesym(tetopa, worktet1);
12240 bond(worktet, worktet1);
12243 if (pointtype(pa) == UNUSEDVERTEX) {
12244 setpointtype(pa, VOLVERTEX);
12246 if (pointtype(pb) == UNUSEDVERTEX) {
12247 setpointtype(pb, VOLVERTEX);
12249 if (pointtype(pc) == UNUSEDVERTEX) {
12250 setpointtype(pc, VOLVERTEX);
12252 if (pointtype(pd) == UNUSEDVERTEX) {
12253 setpointtype(pd, VOLVERTEX);
12256 setpoint2tet(pa, encode(firsttet));
12257 setpoint2tet(pb, encode(firsttet));
12258 setpoint2tet(pc, encode(firsttet));
12259 setpoint2tet(pd, encode(firsttet));
12262 recenttet = firsttet;
12273 void tetgenmesh::incrementaldelaunay(clock_t& tv)
12276 point *permutarray, swapvertex;
12277 REAL v1[3], v2[3], n[3];
12278 REAL bboxsize, bboxsize2, bboxsize3, ori;
12284 printf(
"Delaunizing vertices...\n");
12288 permutarray =
new point[in->numberofpoints];
12289 points->traversalinit();
12293 printf(
" Using the input order.\n");
12295 for (i = 0; i < in->numberofpoints; i++) {
12296 permutarray[i] = (point) points->traverse();
12300 printf(
" Permuting vertices.\n");
12302 srand(in->numberofpoints);
12303 for (i = 0; i < in->numberofpoints; i++) {
12304 randindex = rand() % (i + 1);
12305 permutarray[i] = permutarray[randindex];
12306 permutarray[randindex] = (point) points->traverse();
12308 if (b->brio_hilbert) {
12310 printf(
" Sorting vertices.\n");
12312 hilbert_init(in->mesh_dim);
12313 brio_multiscale_sort(permutarray, in->numberofpoints, b->brio_threshold,
12314 b->brio_ratio, &ngroup);
12321 bboxsize = sqrt(norm2(xmax - xmin, ymax - ymin, zmax - zmin));
12322 bboxsize2 = bboxsize * bboxsize;
12323 bboxsize3 = bboxsize2 * bboxsize;
12327 while ((distance(permutarray[0],permutarray[i])/bboxsize)<b->epsilon) {
12329 if (i == in->numberofpoints - 1) {
12330 printf(
"Exception: All vertices are (nearly) identical (Tol = %g).\n",
12332 terminatetetgen(
this, 10);
12337 swapvertex = permutarray[i];
12338 permutarray[i] = permutarray[1];
12339 permutarray[1] = swapvertex;
12346 for (j = 0; j < 3; j++) {
12347 v1[j] = permutarray[1][j] - permutarray[0][j];
12348 v2[j] = permutarray[i][j] - permutarray[0][j];
12351 while ((sqrt(norm2(n[0], n[1], n[2])) / bboxsize2) < b->epsilon) {
12353 if (i == in->numberofpoints - 1) {
12354 printf(
"Exception: All vertices are (nearly) collinear (Tol = %g).\n",
12356 terminatetetgen(
this, 10);
12358 for (j = 0; j < 3; j++) {
12359 v2[j] = permutarray[i][j] - permutarray[0][j];
12365 swapvertex = permutarray[i];
12366 permutarray[i] = permutarray[2];
12367 permutarray[2] = swapvertex;
12372 ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2],
12374 while ((fabs(ori) / bboxsize3) < b->epsilon) {
12376 if (i == in->numberofpoints) {
12377 printf(
"Exception: All vertices are coplanar (Tol = %g).\n",
12379 terminatetetgen(
this, 10);
12381 ori = orient3dfast(permutarray[0], permutarray[1], permutarray[2],
12386 swapvertex = permutarray[i];
12387 permutarray[i] = permutarray[3];
12388 permutarray[3] = swapvertex;
12395 swapvertex = permutarray[0];
12396 permutarray[0] = permutarray[1];
12397 permutarray[1] = swapvertex;
12401 initialdelaunay(permutarray[0], permutarray[1], permutarray[2],
12405 printf(
" Incrementally inserting vertices.\n");
12407 insertvertexflags ivf;
12408 flipconstraints fc;
12421 for (i = 4; i < in->numberofpoints; i++) {
12422 if (pointtype(permutarray[i]) == UNUSEDVERTEX) {
12423 setpointtype(permutarray[i], VOLVERTEX);
12425 if (b->brio_hilbert || b->no_sort) {
12427 searchtet.tet = recenttet.tet;
12430 searchtet.tet = NULL;
12432 ivf.iloc = (int) OUTSIDE;
12434 if (insertpoint(permutarray[i], &searchtet, NULL, NULL, &ivf)) {
12435 if (flipstack != NULL) {
12437 incrementalflip(permutarray[i], (ivf.iloc == (
int) OUTSIDE), &fc);
12440 if (ivf.iloc == (
int) ONVERTEX) {
12442 swapvertex = org(searchtet);
12443 if (b->object != tetgenbehavior::STL) {
12445 printf(
"Warning: Point #%d is coincident with #%d. Ignored!\n",
12446 pointmark(permutarray[i]), pointmark(swapvertex));
12449 setpoint2ppt(permutarray[i], swapvertex);
12450 setpointtype(permutarray[i], DUPLICATEDVERTEX);
12452 }
else if (ivf.iloc == (
int) NEARVERTEX) {
12453 swapvertex = org(searchtet);
12455 printf(
"Warning: Point %d is replaced by point %d.\n",
12456 pointmark(permutarray[i]), pointmark(swapvertex));
12457 printf(
" Avoid creating a very short edge (len = %g) (< %g).\n",
12458 permutarray[i][3], minedgelength);
12459 printf(
" You may try a smaller tolerance (-T) (current is %g)\n",
12461 printf(
" or use the option -M0/1 to avoid such replacement.\n");
12464 setpoint2ppt(permutarray[i], swapvertex);
12465 setpointtype(permutarray[i], DUPLICATEDVERTEX);
12467 }
else if (ivf.iloc == (
int) NONREGULAR) {
12470 printf(
" Point #%d is non-regular, skipped.\n",
12471 pointmark(permutarray[i]));
12473 setpointtype(permutarray[i], NREGULARVERTEX);
12481 delete [] permutarray;
12498 void tetgenmesh::flipshpush(face* flipedge)
12500 badface *newflipface;
12502 newflipface = (badface *) flippool->alloc();
12503 newflipface->ss = *flipedge;
12504 newflipface->forg = sorg(*flipedge);
12505 newflipface->fdest = sdest(*flipedge);
12506 newflipface->nextitem = flipstack;
12507 flipstack = newflipface;
12520 void tetgenmesh::flip22(face* flipfaces,
int flipflag,
int chkencflag)
12522 face bdedges[4], outfaces[4], infaces[4];
12525 point pa, pb, pc, pd;
12528 pa = sorg(flipfaces[0]);
12529 pb = sdest(flipfaces[0]);
12530 pc = sapex(flipfaces[0]);
12531 pd = sapex(flipfaces[1]);
12533 if (sorg(flipfaces[1]) != pb) {
12534 sesymself(flipfaces[1]);
12540 senext(flipfaces[0], bdedges[0]);
12541 senext2(flipfaces[0], bdedges[1]);
12542 senext(flipfaces[1], bdedges[2]);
12543 senext2(flipfaces[1], bdedges[3]);
12546 for (i = 0; i < 4; i++) {
12547 spivot(bdedges[i], outfaces[i]);
12548 infaces[i] = outfaces[i];
12549 sspivot(bdedges[i], bdsegs[i]);
12550 if (outfaces[i].sh != NULL) {
12551 if (isshsubseg(bdedges[i])) {
12552 spivot(infaces[i], checkface);
12553 while (checkface.sh != bdedges[i].sh) {
12554 infaces[i] = checkface;
12555 spivot(infaces[i], checkface);
12566 setshvertices(flipfaces[0], pc, pd, pb);
12568 setshvertices(flipfaces[1], pd, pc, pa);
12571 if (pointtype(pa) == FREEFACETVERTEX) {
12572 setpoint2sh(pa, sencode(flipfaces[1]));
12574 if (pointtype(pb) == FREEFACETVERTEX) {
12575 setpoint2sh(pb, sencode(flipfaces[0]));
12577 if (pointtype(pc) == FREEFACETVERTEX) {
12578 setpoint2sh(pc, sencode(flipfaces[0]));
12580 if (pointtype(pd) == FREEFACETVERTEX) {
12581 setpoint2sh(pd, sencode(flipfaces[0]));
12585 for (i = 0; i < 4; i++) {
12586 if (outfaces[(3 + i) % 4].sh != NULL) {
12588 if (bdsegs[(3 + i) % 4].sh != NULL) {
12589 bdsegs[(3 + i) % 4].shver = 0;
12590 if (sorg(bdedges[i]) != sorg(bdsegs[(3 + i) % 4])) {
12591 sesymself(bdedges[i]);
12594 sbond1(bdedges[i], outfaces[(3 + i) % 4]);
12595 sbond1(infaces[(3 + i) % 4], bdedges[i]);
12597 sdissolve(bdedges[i]);
12599 if (bdsegs[(3 + i) % 4].sh != NULL) {
12600 ssbond(bdedges[i], bdsegs[(3 + i) % 4]);
12601 if (chkencflag & 1) {
12603 enqueuesubface(badsubsegs, &(bdsegs[(3 + i) % 4]));
12606 ssdissolve(bdedges[i]);
12610 if (chkencflag & 2) {
12612 for (i = 0; i < 2; i++) {
12613 enqueuesubface(badsubfacs, &(flipfaces[i]));
12617 recentsh = flipfaces[0];
12621 for (i = 0; i < 4; i++) {
12622 flipshpush(&(bdedges[i]));
12642 void tetgenmesh::flip31(face* flipfaces,
int flipflag)
12644 face bdedges[3], outfaces[3], infaces[3];
12650 pa = sdest(flipfaces[0]);
12651 pb = sdest(flipfaces[1]);
12652 pc = sdest(flipfaces[2]);
12657 for (i = 0; i < 3; i++) {
12658 senext(flipfaces[i], bdedges[i]);
12659 spivot(bdedges[i], outfaces[i]);
12660 infaces[i] = outfaces[i];
12661 sspivot(bdedges[i], bdsegs[i]);
12662 if (outfaces[i].sh != NULL) {
12663 if (isshsubseg(bdedges[i])) {
12664 spivot(infaces[i], checkface);
12665 while (checkface.sh != bdedges[i].sh) {
12666 infaces[i] = checkface;
12667 spivot(infaces[i], checkface);
12674 makeshellface(subfaces, &(flipfaces[3]));
12675 setshvertices(flipfaces[3], pa, pb,pc);
12676 setshellmark(flipfaces[3], shellmark(flipfaces[0]));
12677 if (checkconstraints) {
12679 setareabound(flipfaces[3], areabound(flipfaces[0]));
12681 if (useinsertradius) {
12682 setfacetindex(flipfaces[3], getfacetindex(flipfaces[0]));
12686 if (pointtype(pa) == FREEFACETVERTEX) {
12687 setpoint2sh(pa, sencode(flipfaces[3]));
12689 if (pointtype(pb) == FREEFACETVERTEX) {
12690 setpoint2sh(pb, sencode(flipfaces[3]));
12692 if (pointtype(pc) == FREEFACETVERTEX) {
12693 setpoint2sh(pc, sencode(flipfaces[3]));
12697 bdedges[0] = flipfaces[3];
12698 senext(flipfaces[3], bdedges[1]);
12699 senext2(flipfaces[3], bdedges[2]);
12702 for (i = 0; i < 3; i++) {
12703 if (outfaces[i].sh != NULL) {
12705 if (bdsegs[i].sh != NULL) {
12706 bdsegs[i].shver = 0;
12707 if (sorg(bdedges[i]) != sorg(bdsegs[i])) {
12708 sesymself(bdedges[i]);
12711 sbond1(bdedges[i], outfaces[i]);
12712 sbond1(infaces[i], bdedges[i]);
12714 if (bdsegs[i].sh != NULL) {
12715 ssbond(bdedges[i], bdsegs[i]);
12719 recentsh = flipfaces[3];
12723 for (i = 0; i < 3; i++) {
12724 flipshpush(&(bdedges[i]));
12735 long tetgenmesh::lawsonflip()
12739 point pa, pb, pc, pd;
12741 long flipcount = 0;
12743 if (b->verbose > 2) {
12744 printf(
" Lawson flip %ld edges.\n", flippool->items);
12747 while (flipstack != (badface *) NULL) {
12750 popface = flipstack;
12751 flipfaces[0] = popface->ss;
12752 pa = popface->forg;
12753 pb = popface->fdest;
12754 flipstack = popface->nextitem;
12755 flippool->dealloc((
void *) popface);
12758 if (flipfaces[0].sh[3] == NULL)
continue;
12760 if ((sorg(flipfaces[0]) != pa) || (sdest(flipfaces[0]) != pb))
continue;
12762 if (isshsubseg(flipfaces[0]))
continue;
12765 spivot(flipfaces[0], flipfaces[1]);
12766 if (flipfaces[1].sh == NULL)
continue;
12767 pc = sapex(flipfaces[0]);
12768 pd = sapex(flipfaces[1]);
12770 sign = incircle3d(pa, pb, pc, pd);
12774 flip22(flipfaces, 1, 0);
12779 if (b->verbose > 2) {
12780 printf(
" Performed %ld flips.\n", flipcount);
12817 int tetgenmesh::sinsertvertex(point insertpt, face *searchsh, face *splitseg,
12818 int iloc,
int bowywat,
int rflag)
12820 face cavesh, neighsh, *parysh;
12821 face newsh, casout, casin;
12824 enum locateresult loc = OUTSIDE;
12828 if (b->verbose > 2) {
12829 printf(
" Insert facet point %d.\n", pointmark(insertpt));
12832 if (bowywat == 3) {
12836 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
12838 spivot(*splitseg, *searchsh);
12839 if (loc != INSTAR) loc = ONEDGE;
12841 if (loc != INSTAR) loc = (
enum locateresult) iloc;
12842 if (loc == OUTSIDE) {
12844 if (searchsh->sh == NULL) {
12845 *searchsh = recentsh;
12848 loc = slocate(insertpt, searchsh, 1, 1, rflag);
12854 if (loc == ONFACE) {
12856 smarktest(*searchsh);
12857 caveshlist->newindex((
void **) &parysh);
12858 *parysh = *searchsh;
12859 }
else if (loc == ONEDGE) {
12860 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
12861 splitseg->shver = 0;
12862 pa = sorg(*splitseg);
12864 pa = sorg(*searchsh);
12866 if (searchsh->sh != NULL) {
12868 neighsh = *searchsh;
12871 if (sorg(neighsh) != pa) sesymself(neighsh);
12873 smarktest(neighsh);
12874 caveshlist->newindex((
void **) &parysh);
12877 cavesegshlist->newindex((
void **) &parysh);
12880 spivotself(neighsh);
12882 if (neighsh.sh == searchsh->sh)
break;
12883 if (neighsh.sh == NULL)
break;
12886 }
else if (loc == ONVERTEX) {
12888 }
else if (loc == OUTSIDE) {
12896 neighsh = *searchsh;
12898 senext2self(neighsh);
12899 spivot(neighsh, casout);
12900 if (casout.sh == NULL) {
12902 ori = orient3d(sorg(neighsh), sdest(neighsh), dummypoint, insertpt);
12904 *searchsh = neighsh;
12909 if (sorg(casout) != sdest(neighsh)) sesymself(casout);
12915 pa = sorg(*searchsh);
12916 pb = sdest(*searchsh);
12919 makeshellface(subfaces, &newsh);
12920 setshvertices(newsh, pb, pa, insertpt);
12921 setshellmark(newsh, shellmark(*searchsh));
12922 if (checkconstraints) {
12924 setareabound(newsh, areabound(*searchsh));
12926 if (useinsertradius) {
12927 setfacetindex(newsh, getfacetindex(*searchsh));
12930 sbond1(newsh, *searchsh);
12931 sbond1(*searchsh, newsh);
12933 if (casin.sh != NULL) {
12934 senext(newsh, casout);
12935 sbond1(casout, casin);
12936 sbond1(casin, casout);
12939 senext2(newsh, casin);
12942 caveshlist->newindex((
void **) &parysh);
12945 neighsh = *searchsh;
12947 senextself(neighsh);
12948 spivot(neighsh, casout);
12949 if (casout.sh == NULL) {
12950 *searchsh = neighsh;
12953 if (sorg(casout) != sdest(neighsh)) sesymself(casout);
12957 pa = sorg(*searchsh);
12958 pb = sdest(*searchsh);
12959 ori = orient3d(pa, pb, dummypoint, insertpt);
12961 if (ori >= 0)
break;
12963 }
else if (loc == INSTAR) {
12969 for (i = 0; i < caveshlist->objects; i++) {
12970 cavesh = * (face *) fastlookup(caveshlist, i);
12971 for (j = 0; j < 3; j++) {
12972 if (!isshsubseg(cavesh)) {
12973 spivot(cavesh, neighsh);
12974 if (neighsh.sh != NULL) {
12976 if (!smarktested(neighsh)) {
12978 if (loc == INSTAR) {
12983 if (!isshtet(neighsh)) {
12985 sign = incircle3d(sorg(neighsh), sdest(neighsh),
12986 sapex(neighsh), insertpt);
12994 smarktest(neighsh);
12995 caveshlist->newindex((
void **) &parysh);
13006 if (loc == OUTSIDE) {
13008 if ((sorg(cavesh) == insertpt) || (sdest(cavesh) == insertpt)) {
13023 caveshbdlist->newindex((
void **) &parysh);
13026 senextself(cavesh);
13032 for (i = 0; i < caveshbdlist->objects; i++) {
13033 parysh = (face *) fastlookup(caveshbdlist, i);
13034 sspivot(*parysh, checkseg);
13035 if ((parysh->shver & 01) != 0) sesymself(*parysh);
13036 pa = sorg(*parysh);
13037 pb = sdest(*parysh);
13039 makeshellface(subfaces, &newsh);
13040 setshvertices(newsh, pa, pb, insertpt);
13041 setshellmark(newsh, shellmark(*parysh));
13042 if (checkconstraints) {
13044 setareabound(newsh, areabound(*parysh));
13046 if (useinsertradius) {
13047 setfacetindex(newsh, getfacetindex(*parysh));
13050 if (pointtype(pa) == FREEFACETVERTEX) {
13051 setpoint2sh(pa, sencode(newsh));
13053 if (pointtype(pb) == FREEFACETVERTEX) {
13054 setpoint2sh(pb, sencode(newsh));
13057 spivot(*parysh, casout);
13058 if (casout.sh != NULL) {
13060 if (checkseg.sh != NULL) {
13062 checkseg.shver = 0;
13063 if (sorg(newsh) != sorg(checkseg)) {
13065 sesymself(*parysh);
13067 spivot(casin, neighsh);
13068 while (neighsh.sh != parysh->sh) {
13070 spivot(casin, neighsh);
13073 sbond1(newsh, casout);
13074 sbond1(casin, newsh);
13076 if (checkseg.sh != NULL) {
13077 ssbond(newsh, checkseg);
13081 sbond1(*parysh, newsh);
13084 if (newsh.sh != NULL) {
13090 if (pointtype(insertpt) == FREEFACETVERTEX) {
13091 setpoint2sh(insertpt, sencode(newsh));
13095 for (i = 0; i < caveshbdlist->objects; i++) {
13097 parysh = (face *) fastlookup(caveshbdlist, i);
13098 spivot(*parysh, newsh);
13100 spivot(newsh, neighsh);
13101 if (neighsh.sh == NULL) {
13103 pb = sdest(*parysh);
13106 senextself(neighsh);
13107 spivotself(neighsh);
13108 if (neighsh.sh == NULL)
break;
13109 if (!smarktested(neighsh))
break;
13110 if (sdest(neighsh) != pb) sesymself(neighsh);
13112 if (neighsh.sh != NULL) {
13114 if (sorg(neighsh) != pb) sesymself(neighsh);
13115 senext2self(neighsh);
13116 sbond(newsh, neighsh);
13119 spivot(*parysh, newsh);
13120 senext2self(newsh);
13121 spivot(newsh, neighsh);
13122 if (neighsh.sh == NULL) {
13124 pa = sorg(*parysh);
13127 senext2self(neighsh);
13128 spivotself(neighsh);
13129 if (neighsh.sh == NULL)
break;
13130 if (!smarktested(neighsh))
break;
13131 if (sorg(neighsh) != pa) sesymself(neighsh);
13133 if (neighsh.sh != NULL) {
13135 if (sdest(neighsh) != pa) sesymself(neighsh);
13136 senextself(neighsh);
13137 sbond(newsh, neighsh);
13142 if ((loc == ONEDGE) || ((splitseg != NULL) && (splitseg->sh != NULL))
13143 || (cavesegshlist->objects > 0l)) {
13149 face aseg, bseg, aoutseg, boutseg;
13151 for (i = 0; i < cavesegshlist->objects; i++) {
13153 parysh = (face *) fastlookup(cavesegshlist, i);
13155 spivot(*parysh, cavesh);
13156 if (sapex(cavesh) == insertpt) {
13158 if (cavesegshlist->objects > 1) {
13160 j = (i + 1) % (
int) cavesegshlist->objects;
13161 parysh = (face *) fastlookup(cavesegshlist, j);
13162 spivot(*parysh, neighsh);
13164 if (sorg(neighsh) != sorg(cavesh)) {
13165 sesymself(neighsh);
13172 for (j = 0; j < 2; j++) {
13173 senextself(cavesh);
13174 senextself(neighsh);
13175 spivot(cavesh, newsh);
13176 spivot(neighsh, casout);
13177 sbond1(newsh, casout);
13184 for (j = 0; j < 2; j++) {
13185 senextself(cavesh);
13186 spivot(cavesh, newsh);
13192 if (pointtype(insertpt) == FREEFACETVERTEX) {
13193 setpoint2sh(insertpt, sencode(newsh));
13198 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
13199 if (loc != INSTAR) {
13200 smarktest(*splitseg);
13204 pa = sorg(*splitseg);
13205 pb = sdest(*splitseg);
13208 makeshellface(subsegs, &aseg);
13209 makeshellface(subsegs, &bseg);
13211 setshvertices(aseg, pa, insertpt, NULL);
13212 setshvertices(bseg, insertpt, pb, NULL);
13213 setshellmark(aseg, shellmark(*splitseg));
13214 setshellmark(bseg, shellmark(*splitseg));
13215 if (checkconstraints) {
13216 setareabound(aseg, areabound(*splitseg));
13217 setareabound(bseg, areabound(*splitseg));
13219 if (useinsertradius) {
13220 setfacetindex(aseg, getfacetindex(*splitseg));
13221 setfacetindex(bseg, getfacetindex(*splitseg));
13225 senext2(*splitseg, boutseg);
13226 spivotself(boutseg);
13227 if (boutseg.sh != NULL) {
13228 senext2(aseg, aoutseg);
13229 sbond(boutseg, aoutseg);
13232 senext(*splitseg, aoutseg);
13233 spivotself(aoutseg);
13234 if (aoutseg.sh != NULL) {
13235 senext(bseg, boutseg);
13236 sbond(boutseg, aoutseg);
13239 senext(aseg, aoutseg);
13240 senext2(bseg, boutseg);
13241 sbond(aoutseg, boutseg);
13246 for (i = 0; i < cavesegshlist->objects; i++) {
13247 parysh = (face *) fastlookup(cavesegshlist, i);
13248 spivot(*parysh, neighsh);
13250 if (sorg(neighsh) != pa) {
13251 sesymself(neighsh);
13253 senext2(neighsh, newsh);
13255 ssbond(newsh, aseg);
13256 senext(neighsh, newsh);
13258 ssbond(newsh, bseg);
13263 if (pointtype(insertpt) == FREESEGVERTEX) {
13264 setpoint2sh(insertpt, sencode(aseg));
13267 if (pointtype(pa) == FREESEGVERTEX) {
13268 setpoint2sh(pa, sencode(aseg));
13270 if (pointtype(pb) == FREESEGVERTEX) {
13271 setpoint2sh(pb, sencode(bseg));
13276 for (i = 0; i < cavesegshlist->objects; i++) {
13277 parysh = (face *) fastlookup(cavesegshlist, i);
13278 spivotself(*parysh);
13279 if (sapex(*parysh) == insertpt) {
13280 shellfacedealloc(subfaces, parysh->sh);
13283 cavesegshlist->restart();
13285 if ((splitseg != NULL) && (splitseg->sh != NULL)) {
13288 cavesegshlist->newindex((
void **) &parysh);
13290 cavesegshlist->newindex((
void **) &parysh);
13318 int tetgenmesh::sremovevertex(point delpt, face* parentsh, face* parentseg,
13321 face flipfaces[4], spinsh, *parysh;
13322 point pa, pb, pc, pd;
13326 if (parentseg != NULL) {
13329 face startsh, neighsh, nextsh;
13330 face abseg, prevseg, checkseg;
13331 face adjseg1, adjseg2;
13333 senext2(*parentseg, prevseg);
13334 spivotself(prevseg);
13337 pa = sorg(prevseg);
13338 pb = sdest(*parentseg);
13339 if (b->verbose > 2) {
13340 printf(
" Remove vertex %d from segment [%d, %d].\n",
13341 pointmark(delpt), pointmark(pa), pointmark(pb));
13343 makeshellface(subsegs, &abseg);
13344 setshvertices(abseg, pa, pb, NULL);
13345 setshellmark(abseg, shellmark(*parentseg));
13346 if (checkconstraints) {
13347 setareabound(abseg, areabound(*parentseg));
13349 if (useinsertradius) {
13350 setfacetindex(abseg, getfacetindex(*parentseg));
13353 senext2(prevseg, adjseg1);
13354 spivotself(adjseg1);
13355 if (adjseg1.sh != NULL) {
13357 senextself(adjseg1);
13358 senext2(abseg, adjseg2);
13359 sbond(adjseg1, adjseg2);
13362 senext(*parentseg, adjseg1);
13363 spivotself(adjseg1);
13364 if (adjseg1.sh != NULL) {
13366 senext2self(adjseg1);
13367 senext(abseg, adjseg2);
13368 sbond(adjseg1, adjseg2);
13371 setpoint2sh(pa, sencode(abseg));
13372 setpoint2sh(pb, sencode(abseg));
13376 spivot(*parentseg, *parentsh);
13377 if (parentsh->sh != NULL) {
13378 spinsh = *parentsh;
13381 caveshlist->newindex((
void **) &parysh);
13384 spivotself(spinsh);
13385 if (spinsh.sh == NULL) {
13388 if (spinsh.sh == parentsh->sh)
break;
13394 for (i = 0; i < caveshlist->objects; i++) {
13395 parysh = (face *) fastlookup(caveshlist, i);
13397 if (sorg(startsh) != delpt) {
13398 sesymself(startsh);
13403 senext2self(neighsh);
13404 sspivot(neighsh, checkseg);
13405 if (checkseg.sh != NULL) {
13409 spivotself(neighsh);
13410 if (sorg(neighsh) != delpt) sesymself(neighsh);
13413 if (neighsh.sh != startsh.sh) {
13415 ssdissolve(startsh);
13416 ssdissolve(neighsh);
13420 makeshellface(subfaces, &fakesh);
13421 setshvertices(fakesh, pa, pb, delpt);
13422 setshellmark(fakesh, shellmark(startsh));
13424 ssbond(fakesh, abseg);
13426 senext(fakesh, nextsh);
13427 sbond(nextsh, startsh);
13428 senext2(fakesh, nextsh);
13429 sbond(nextsh, neighsh);
13434 senext2self(neighsh);
13437 spivot(neighsh, startsh);
13438 if (sorg(startsh) != pa) sesymself(startsh);
13439 sdissolve(startsh);
13441 ssbond(startsh, abseg);
13444 shellfacedealloc(subfaces, neighsh.sh);
13447 cavesegshlist->newindex((
void **) &parysh);
13450 caveshlist->restart();
13453 if (cavesegshlist->objects > 1) {
13454 for (i = 0; i < cavesegshlist->objects; i++) {
13455 parysh = (face *) fastlookup(cavesegshlist, i);
13458 j = (i + 1) % cavesegshlist->objects;
13459 parysh = (face *) fastlookup(cavesegshlist, j);
13461 sbond1(fakesh, nextsh);
13466 shellfacedealloc(subsegs, parentseg->sh);
13467 shellfacedealloc(subsegs, prevseg.sh);
13469 *parentseg = abseg;
13472 if (b->verbose > 2) {
13473 printf(
" Remove vertex %d from surface.\n", pointmark(delpt));
13476 senextself(*parentsh);
13478 cavesegshlist->newindex((
void **) &parysh);
13479 *parysh = *parentsh;
13484 for (it = 0; it < cavesegshlist->objects; it++) {
13485 parentsh = (face *) fastlookup(cavesegshlist, it);
13486 senextself(*parentsh);
13487 spivotself(*parentsh);
13488 if (sorg(*parentsh) != delpt) sesymself(*parentsh);
13490 if (sorg(*parentsh) != delpt) {
13497 spinsh = *parentsh;
13499 caveshlist->newindex((
void **) &parysh);
13501 senext2self(spinsh);
13502 spivotself(spinsh);
13503 if (spinsh.sh == parentsh->sh)
break;
13504 if (sorg(spinsh) != delpt) sesymself(spinsh);
13507 if (caveshlist->objects == 3) {
13509 for (i = 0; i < 3; i++) {
13510 parysh = (face *) fastlookup(caveshlist, i);
13511 flipfaces[i] = *parysh;
13513 flip31(flipfaces, lawson);
13514 for (i = 0; i < 3; i++) {
13515 shellfacedealloc(subfaces, flipfaces[i].sh);
13517 caveshlist->restart();
13519 caveshbdlist->newindex((
void **) &parysh);
13520 *parysh = flipfaces[3];
13526 for (i = 0; i < caveshlist->objects; i++) {
13527 parysh = (face *) fastlookup(caveshlist, i);
13528 flipfaces[0] = *parysh;
13529 spivot(flipfaces[0], flipfaces[1]);
13530 if (sorg(flipfaces[0]) != sdest(flipfaces[1]))
13531 sesymself(flipfaces[1]);
13533 if (!smarktested(flipfaces[0]) && !smarktested(flipfaces[1])) {
13534 pa = sorg(flipfaces[0]);
13535 pb = sdest(flipfaces[0]);
13536 pc = sapex(flipfaces[0]);
13537 pd = sapex(flipfaces[1]);
13538 calculateabovepoint4(pa, pb, pc, pd);
13540 ori1 = orient3d(pc, pd, dummypoint, pa);
13541 ori2 = orient3d(pc, pd, dummypoint, pb);
13542 if (ori1 * ori2 < 0) {
13544 flip22(flipfaces, lawson, 0);
13547 senext2(flipfaces[1], *parentsh);
13549 caveshbdlist->newindex((
void **) &parysh);
13550 *parysh = flipfaces[0];
13556 if (i == caveshlist->objects) {
13558 parysh = (face *) fastlookup(caveshlist, 0);
13559 flipfaces[0] = *parysh;
13560 spivot(flipfaces[0], flipfaces[1]);
13561 if (sorg(flipfaces[0]) != sdest(flipfaces[1])) {
13562 sesymself(flipfaces[1]);
13564 flip22(flipfaces, lawson, 0);
13565 senext2(flipfaces[1], *parentsh);
13567 caveshbdlist->newindex((
void **) &parysh);
13568 *parysh = flipfaces[0];
13572 caveshlist->restart();
13577 cavesegshlist->restart();
13579 if (b->verbose > 2) {
13580 printf(
" Created %ld new subfaces.\n", caveshbdlist->objects);
13618 enum tetgenmesh::locateresult tetgenmesh::slocate(point searchpt,
13619 face* searchsh,
int aflag,
int cflag,
int rflag)
13623 enum locateresult loc;
13624 enum {MOVE_BC, MOVE_CA} nextmove;
13625 REAL ori, ori_bc, ori_ca;
13628 pa = sorg(*searchsh);
13629 pb = sdest(*searchsh);
13630 pc = sapex(*searchsh);
13634 calculateabovepoint4(pa, pb, pc, searchpt);
13638 ori = orient3d(pa, pb, pc, dummypoint);
13640 sesymself(*searchsh);
13641 }
else if (ori == 0.0) {
13647 for (i = 0; i < 3; i++) {
13648 pa = sorg(*searchsh);
13649 pb = sdest(*searchsh);
13650 ori = orient3d(pa, pb, dummypoint, searchpt);
13651 if (ori > 0)
break;
13652 senextself(*searchsh);
13658 pc = sapex(*searchsh);
13660 if (pc == searchpt) {
13661 senext2self(*searchsh);
13667 ori_bc = orient3d(pb, pc, dummypoint, searchpt);
13668 ori_ca = orient3d(pc, pa, dummypoint, searchpt);
13673 if (randomnation(2)) {
13674 nextmove = MOVE_CA;
13676 nextmove = MOVE_BC;
13680 nextmove = MOVE_BC;
13685 nextmove = MOVE_CA;
13692 senext2self(*searchsh);
13698 senextself(*searchsh);
13703 senext2self(*searchsh);
13711 if (nextmove == MOVE_BC) {
13712 senextself(*searchsh);
13714 senext2self(*searchsh);
13718 if (isshsubseg(*searchsh)) {
13722 spivot(*searchsh, neighsh);
13723 if (neighsh.sh == NULL) {
13727 if (sorg(neighsh) != sdest(*searchsh)) {
13728 sesymself(neighsh);
13732 *searchsh = neighsh;
13733 pa = sorg(*searchsh);
13734 pb = sdest(*searchsh);
13735 pc = sapex(*searchsh);
13737 if (pc == searchpt) {
13738 senext2self(*searchsh);
13749 REAL n[3], area_abc, area_abp, area_bcp, area_cap;
13751 pa = sorg(*searchsh);
13752 pb = sdest(*searchsh);
13753 pc = sapex(*searchsh);
13755 facenormal(pa, pb, pc, n, 1, NULL);
13756 area_abc = sqrt(dot(n, n));
13758 facenormal(pb, pc, searchpt, n, 1, NULL);
13759 area_bcp = sqrt(dot(n, n));
13760 if ((area_bcp / area_abc) < b->epsilon) {
13764 facenormal(pc, pa, searchpt, n, 1, NULL);
13765 area_cap = sqrt(dot(n, n));
13766 if ((area_cap / area_abc) < b->epsilon) {
13770 if ((loc == ONFACE) || (loc == OUTSIDE)) {
13771 facenormal(pa, pb, searchpt, n, 1, NULL);
13772 area_abp = sqrt(dot(n, n));
13773 if ((area_abp / area_abc) < b->epsilon) {
13780 if (area_abp == 0) {
13781 if (area_bcp == 0) {
13782 senextself(*searchsh);
13785 if (area_cap == 0) {
13791 }
else if (area_bcp == 0) {
13792 if (area_cap == 0) {
13793 senext2self(*searchsh);
13796 senextself(*searchsh);
13799 }
else if (area_cap == 0) {
13800 senext2self(*searchsh);
13826 enum tetgenmesh::interresult tetgenmesh::sscoutsegment(face *searchsh,
13827 point endpt,
int insertsegflag,
int reporterrorflag,
int chkencflag)
13829 face flipshs[2], neighsh;
13830 point startpt, pa, pb, pc, pd;
13831 enum interresult dir;
13832 enum {MOVE_AB, MOVE_CA} nextmove;
13833 REAL ori_ab, ori_ca, len;
13837 startpt = sorg(*searchsh);
13838 nextmove = MOVE_AB;
13840 if (b->verbose > 2) {
13841 printf(
" Scout segment (%d, %d).\n", pointmark(startpt),
13844 len = distance(startpt, endpt);
13849 pb = sdest(*searchsh);
13855 pc = sapex(*searchsh);
13857 senext2self(*searchsh);
13858 sesymself(*searchsh);
13865 if ((sqrt(triarea(startpt, pb, endpt)) / len) < b->epsilon) {
13868 ori_ab = orient3d(startpt, pb, dummypoint, endpt);
13870 if ((sqrt(triarea(pc, startpt, endpt)) / len) < b->epsilon) {
13873 ori_ca = orient3d(pc, startpt, dummypoint, endpt);
13879 if (randomnation(2)) {
13880 nextmove = MOVE_CA;
13882 nextmove = MOVE_AB;
13885 nextmove = MOVE_AB;
13889 nextmove = MOVE_CA;
13898 senext2self(*searchsh);
13899 sesymself(*searchsh);
13910 terminatetetgen(
this, 2);
13917 if (nextmove == MOVE_AB) {
13920 if (isshsubseg(*searchsh)) {
13924 spivot(*searchsh, neighsh);
13925 if (neighsh.sh != NULL) {
13926 if (sorg(neighsh) != pb) sesymself(neighsh);
13927 senext(neighsh, *searchsh);
13931 senext2(*searchsh, neighsh);
13934 if (isshsubseg(neighsh)) {
13935 *searchsh = neighsh;
13939 spivotself(neighsh);
13940 if (sdest(neighsh) != pc) sesymself(neighsh);
13941 *searchsh = neighsh;
13944 senext2(*searchsh, neighsh);
13947 if (isshsubseg(neighsh)) {
13948 *searchsh = neighsh;
13952 spivotself(neighsh);
13953 if (neighsh.sh != NULL) {
13954 if (sdest(neighsh) != pc) sesymself(neighsh);
13955 *searchsh = neighsh;
13961 if (isshsubseg(*searchsh)) {
13965 spivot(*searchsh, neighsh);
13966 if (sorg(neighsh) != pb) sesymself(neighsh);
13967 senext(neighsh, *searchsh);
13972 if (dir == SHAREEDGE) {
13973 if (insertsegflag) {
13976 makeshellface(subsegs, &newseg);
13977 setshvertices(newseg, startpt, endpt, NULL);
13979 setshellmark(newseg, -1);
13980 ssbond(*searchsh, newseg);
13981 spivot(*searchsh, neighsh);
13982 if (neighsh.sh != NULL) {
13983 ssbond(neighsh, newseg);
13989 if (dir == ACROSSVERT) {
13991 if (reporterrorflag) {
13992 point pp = sdest(*searchsh);
13993 printf(
"PLC Error: A vertex lies in a segment in facet #%d.\n",
13994 shellmark(*searchsh));
13995 printf(
" Vertex: [%d] (%g,%g,%g).\n",pointmark(pp),pp[0],pp[1],pp[2]);
13996 printf(
" Segment: [%d, %d]\n", pointmark(startpt), pointmark(endpt));
14001 if (dir == ACROSSEDGE) {
14003 senext(*searchsh, flipshs[0]);
14004 if (isshsubseg(flipshs[0])) {
14005 if (reporterrorflag) {
14006 REAL P[3], Q[3], tp = 0, tq = 0;
14007 linelineint(startpt, endpt, pb, pc, P, Q, &tp, &tq);
14008 printf(
"PLC Error: Two segments intersect at point (%g,%g,%g),",
14010 printf(
" in facet #%d.\n", shellmark(*searchsh));
14011 printf(
" Segment 1: [%d, %d]\n", pointmark(pb), pointmark(pc));
14012 printf(
" Segment 2: [%d, %d]\n", pointmark(startpt),pointmark(endpt));
14017 spivot(flipshs[0], flipshs[1]);
14018 if (sorg(flipshs[1]) != sdest(flipshs[0])) sesymself(flipshs[1]);
14019 flip22(flipshs, 1, 0);
14021 pa = sapex(flipshs[1]);
14022 pb = sapex(flipshs[0]);
14023 pc = sorg(flipshs[0]);
14024 pd = sdest(flipshs[0]);
14027 ori_ab = orient3d(pc, pd, dummypoint, pb);
14028 ori_ca = orient3d(pd, pc, dummypoint, pa);
14030 flipshpush(&(flipshs[0]));
14031 }
else if (ori_ca <= 0) {
14032 flipshpush(&(flipshs[1]));
14035 *searchsh = flipshs[0];
14038 return sscoutsegment(searchsh, endpt, insertsegflag, reporterrorflag,
14050 void tetgenmesh::scarveholes(
int holes, REAL* holelist)
14052 face *parysh, searchsh, neighsh;
14053 enum locateresult loc;
14057 smarktest(recentsh);
14058 caveshlist->newindex((
void **) &parysh);
14059 *parysh = recentsh;
14060 for (i = 0; i < caveshlist->objects; i++) {
14061 parysh = (face *) fastlookup(caveshlist, i);
14062 searchsh = *parysh;
14063 searchsh.shver = 0;
14064 for (j = 0; j < 3; j++) {
14065 spivot(searchsh, neighsh);
14067 if (neighsh.sh != NULL) {
14068 if (!smarktested(neighsh)) {
14069 smarktest(neighsh);
14070 caveshlist->newindex((
void **) &parysh);
14075 if (!isshsubseg(searchsh)) {
14077 if (!sinfected(searchsh)) {
14079 caveshbdlist->newindex((
void **) &parysh);
14080 *parysh = searchsh;
14084 senextself(searchsh);
14089 for (i = 0; i < 3 * holes; i += 3) {
14090 searchsh = recentsh;
14091 loc = slocate(&(holelist[i]), &searchsh, 1, 1, 0);
14092 if (loc != OUTSIDE) {
14094 caveshbdlist->newindex((
void **) &parysh);
14095 *parysh = searchsh;
14100 for (i = 0; i < caveshbdlist->objects; i++) {
14101 parysh = (face *) fastlookup(caveshbdlist, i);
14102 searchsh = *parysh;
14103 searchsh.shver = 0;
14104 for (j = 0; j < 3; j++) {
14105 spivot(searchsh, neighsh);
14106 if (neighsh.sh != NULL) {
14107 if (!isshsubseg(searchsh)) {
14108 if (!sinfected(neighsh)) {
14110 caveshbdlist->newindex((
void **) &parysh);
14114 sdissolve(neighsh);
14117 senextself(searchsh);
14122 for (i = 0; i < caveshlist->objects; i++) {
14123 parysh = (face *) fastlookup(caveshlist, i);
14124 if (sinfected(*parysh)) {
14125 shellfacedealloc(subfaces, parysh->sh);
14127 sunmarktest(*parysh);
14131 caveshlist->restart();
14132 caveshbdlist->restart();
14147 int tetgenmesh::triangulate(
int shmark, arraypool* ptlist, arraypool* conlist,
14148 int holes, REAL* holelist)
14150 face searchsh, newsh, *parysh;
14151 face newseg, *paryseg;
14152 point pa, pb, pc, *ppt, *cons;
14156 if (b->verbose > 2) {
14157 printf(
" f%d: %ld vertices, %ld segments", shmark, ptlist->objects,
14160 printf(
", %d holes", holes);
14165 if (ptlist->objects < 2l) {
14168 }
else if (ptlist->objects == 2l) {
14169 pa = * (point *) fastlookup(ptlist, 0);
14170 pb = * (point *) fastlookup(ptlist, 1);
14171 if (distance(pa, pb) > 0) {
14173 makeshellface(subsegs, &newseg);
14174 setshvertices(newseg, pa, pb, NULL);
14175 setshellmark(newseg, -1);
14177 if (pointtype(pa) == VOLVERTEX) {
14178 setpointtype(pa, FACETVERTEX);
14180 if (pointtype(pb) == VOLVERTEX) {
14181 setpointtype(pb, FACETVERTEX);
14184 }
else if (ptlist->objects == 3) {
14185 pa = * (point *) fastlookup(ptlist, 0);
14186 pb = * (point *) fastlookup(ptlist, 1);
14187 pc = * (point *) fastlookup(ptlist, 2);
14190 if (!calculateabovepoint(ptlist, &pa, &pb, &pc)) {
14192 printf(
"Warning: Unable to triangulate facet #%d. Skipped!\n",shmark);
14199 makeshellface(subfaces, &newsh);
14200 setshvertices(newsh, pa, pb, pc);
14201 setshellmark(newsh, shmark);
14204 if (pointtype(pa) == VOLVERTEX) {
14205 setpointtype(pa, FACETVERTEX);
14207 if (pointtype(pb) == VOLVERTEX) {
14208 setpointtype(pb, FACETVERTEX);
14210 if (pointtype(pc) == VOLVERTEX) {
14211 setpointtype(pc, FACETVERTEX);
14215 if (b->quality && (in->facetconstraintlist != NULL)) {
14216 for (i = 0; i < in->numberoffacetconstraints; i++) {
14217 if (shmark == ((
int) in->facetconstraintlist[i * 2])) {
14218 REAL area = in->facetconstraintlist[i * 2 + 1];
14219 setareabound(newsh, area);
14225 if (ptlist->objects == 3) {
14227 for (i = 0; i < 3; i++) {
14228 makeshellface(subsegs, &newseg);
14229 setshvertices(newseg, sorg(newsh), sdest(newsh), NULL);
14230 setshellmark(newseg, -1);
14231 ssbond(newsh, newseg);
14241 caveencshlist->newindex((
void **) &parysh);
14248 for (i = 0; i < ptlist->objects; i++) {
14249 ppt = (point *) fastlookup(ptlist, i);
14250 if (!pinfected(*ppt)) {
14251 searchsh = recentsh;
14252 iloc = (int) OUTSIDE;
14254 iloc = sinsertvertex(*ppt, &searchsh, NULL, iloc, 1, 1);
14255 if (iloc != ((
int) ONVERTEX)) {
14257 if (pointtype(*ppt) == VOLVERTEX) {
14258 setpointtype(*ppt, FACETVERTEX);
14261 for (j = 0; j < caveshbdlist->objects; j++) {
14263 parysh = (face *) fastlookup(caveshbdlist, j);
14264 spivot(*parysh, searchsh);
14266 if (searchsh.sh[3] != NULL) {
14267 caveencshlist->newindex((
void **) &parysh);
14268 *parysh = searchsh;
14272 for (j = 0; j < caveshlist->objects; j++) {
14273 parysh = (face *) fastlookup(caveshlist, j);
14274 shellfacedealloc(subfaces, parysh->sh);
14277 caveshbdlist->restart();
14278 caveshlist->restart();
14279 cavesegshlist->restart();
14290 if (i < ptlist->objects) {
14294 printf(
"Warning: Fail to triangulate facet #%d. Skipped!\n", shmark);
14296 for (i = 0; i < caveencshlist->objects; i++) {
14297 parysh = (face *) fastlookup(caveencshlist, i);
14298 if (parysh->sh[3] != NULL) {
14299 shellfacedealloc(subfaces, parysh->sh);
14302 caveencshlist->restart();
14307 for (i = 0; i < conlist->objects; i++) {
14308 cons = (point *) fastlookup(conlist, i);
14309 searchsh = recentsh;
14310 iloc = (int) slocate(cons[0], &searchsh, 1, 1, 0);
14311 if (iloc != (
int) ONVERTEX) {
14313 subfaces->traversalinit();
14314 searchsh.sh = shellfacetraverse(subfaces);
14315 while (searchsh.sh != NULL) {
14317 if (shellmark(searchsh) == shmark) {
14318 if ((point) searchsh.sh[3] == cons[0]) {
14319 searchsh.shver = 0;
break;
14320 }
else if ((point) searchsh.sh[4] == cons[0]) {
14321 searchsh.shver = 2;
break;
14322 }
else if ((point) searchsh.sh[5] == cons[0]) {
14323 searchsh.shver = 4;
break;
14326 searchsh.sh = shellfacetraverse(subfaces);
14330 if (sscoutsegment(&searchsh, cons[1], 1, 1, 0) != SHAREEDGE) {
14334 sspivot(searchsh, newseg);
14335 caveencseglist->newindex((
void **) &paryseg);
14337 if (flipstack != NULL) {
14343 if (i < conlist->objects) {
14345 printf(
"Warning: Fail to recover a segment in facet #%d. Skipped!\n",
14348 for (i = 0; i < caveencshlist->objects; i++) {
14349 parysh = (face *) fastlookup(caveencshlist, i);
14350 if (parysh->sh[3] != NULL) {
14351 shellfacedealloc(subfaces, parysh->sh);
14354 for (i = 0; i < caveencseglist->objects; i++) {
14355 paryseg = (face *) fastlookup(caveencseglist, i);
14356 if (paryseg->sh[3] != NULL) {
14357 shellfacedealloc(subsegs, paryseg->sh);
14360 caveencshlist->restart();
14361 caveencseglist->restart();
14366 scarveholes(holes, holelist);
14368 caveencshlist->restart();
14369 caveencseglist->restart();
14382 void tetgenmesh::unifysegments()
14384 badface *facelink = NULL, *newlinkitem, *f1, *f2;
14385 face *facperverlist, sface;
14386 face subsegloop, testseg;
14388 REAL ori1, ori2, ori3;
14390 REAL cosang, ang, ang_tol;
14394 if (b->verbose > 1) {
14395 printf(
" Unifying segments.\n");
14398 ang_tol = b->facet_overlap_ang_tol / 180.0 * PI;
14399 if (ang_tol < 0.0) ang_tol = 0.0;
14402 makepoint2submap(subfaces, idx2faclist, facperverlist);
14405 subsegloop.shver = 0;
14406 subsegs->traversalinit();
14407 subsegloop.sh = shellfacetraverse(subsegs);
14408 while (subsegloop.sh != (shellface *) NULL) {
14409 torg = sorg(subsegloop);
14410 tdest = sdest(subsegloop);
14412 idx = pointmark(torg) - in->firstnumber;
14417 for (k = idx2faclist[idx]; k < idx2faclist[idx + 1]; k++) {
14418 sface = facperverlist[k];
14420 if (sface.sh[3] == NULL)
continue;
14422 if (sdest(sface) != tdest) {
14423 senext2self(sface);
14426 if (sdest(sface) != tdest)
continue;
14429 if (flippool->items >= 2) {
14431 for (m = 0; m < flippool->items - 1; m++) {
14433 ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(f2->ss));
14434 ori2 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
14439 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14443 }
else if (ori3 < 0) {
14447 report_overlapping_facets(&(f2->ss), &sface);
14450 }
else if (ori2 < 0) {
14455 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14461 report_overlapping_facets(&(f1->ss), &sface);
14465 }
else if (ori1 < 0) {
14469 }
else if (ori2 < 0) {
14471 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14475 }
else if (ori3 < 0) {
14479 report_overlapping_facets(&(f2->ss), &sface);
14484 ori3 = orient3d(torg, tdest, sapex(f2->ss), sapex(sface));
14487 report_overlapping_facets(&(f1->ss), &sface);
14498 }
else if (ori2 < 0) {
14504 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14505 facenormal(torg, tdest, sapex(sface), n2, 1, NULL);
14506 if (dot(n1, n2) > 0) {
14507 report_overlapping_facets(&(f1->ss), &sface);
14509 report_overlapping_facets(&(f2->ss), &sface);
14517 if (sface.sh[3] != NULL) {
14519 newlinkitem = (badface *) flippool->alloc();
14520 newlinkitem->ss = sface;
14521 newlinkitem->nextitem = f1->nextitem;
14522 f1->nextitem = newlinkitem;
14524 }
else if (flippool->items == 1) {
14527 ori1 = orient3d(torg, tdest, sapex(f1->ss), sapex(sface));
14530 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14531 facenormal(torg, tdest, sapex(sface), n2, 1, NULL);
14532 if (dot(n1, n2) > 0) {
14534 report_overlapping_facets(&(f1->ss), &sface);
14538 if (sface.sh[3] != NULL) {
14540 newlinkitem = (badface *) flippool->alloc();
14541 newlinkitem->ss = sface;
14542 newlinkitem->nextitem = NULL;
14543 f1->nextitem = newlinkitem;
14547 newlinkitem = (badface *) flippool->alloc();
14548 newlinkitem->ss = sface;
14549 newlinkitem->nextitem = NULL;
14550 facelink = newlinkitem;
14558 for (k = 0; k < flippool->items; k++) {
14559 sspivot(f1->ss, testseg);
14561 if ((testseg.sh != subsegloop.sh) && (testseg.sh[3] != NULL)) {
14562 shellfacedealloc(subsegs, testseg.sh);
14565 ssbond(f1->ss, subsegloop);
14570 if (flippool->items > 1) {
14572 for (k = 1; k <= flippool->items; k++) {
14573 k < flippool->items ? f2 = f1->nextitem : f2 = facelink;
14575 facenormal(torg, tdest, sapex(f1->ss), n1, 1, NULL);
14576 facenormal(torg, tdest, sapex(f2->ss), n2, 1, NULL);
14577 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14579 if (cosang > 1.0) cosang = 1.0;
14580 else if (cosang < -1.0) cosang = -1.0;
14581 ang = acos(cosang);
14582 if (ang < ang_tol) {
14584 report_overlapping_facets(&(f1->ss), &(f2->ss), ang);
14587 if (ang < minfacetdihed) {
14588 minfacetdihed = ang;
14590 sbond1(f1->ss, f2->ss);
14596 flippool->restart();
14599 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
14602 for (k = 0; k < in->numberofsegmentconstraints; k++) {
14603 e1 = (int) in->segmentconstraintlist[k * 3];
14604 e2 = (
int) in->segmentconstraintlist[k * 3 + 1];
14605 if (((pointmark(torg) == e1) && (pointmark(tdest) == e2)) ||
14606 ((pointmark(torg) == e2) && (pointmark(tdest) == e1))) {
14607 len = in->segmentconstraintlist[k * 3 + 2];
14608 setareabound(subsegloop, len);
14614 subsegloop.sh = shellfacetraverse(subsegs);
14617 delete [] idx2faclist;
14618 delete [] facperverlist;
14633 void tetgenmesh::identifyinputedges(point *idx2verlist)
14635 face* shperverlist;
14637 face searchsh, neighsh;
14638 face segloop, checkseg, newseg;
14639 point checkpt, pa = NULL, pb = NULL;
14648 printf(
"Inserting edges ...\n");
14652 makepoint2submap(subfaces, idx2shlist, shperverlist);
14655 for (i = 0; i < in->numberofedges; i++) {
14656 endpts = &(in->edgelist[(i << 1)]);
14657 if (endpts[0] == endpts[1]) {
14659 printf(
"Warning: Edge #%d is degenerated. Skipped.\n", i);
14665 edgemarker = in->edgemarkerlist ? in->edgemarkerlist[i] : -2;
14669 searchsh.sh = NULL;
14670 idx = endpts[0] - in->firstnumber;
14671 for (j = idx2shlist[idx]; j < idx2shlist[idx + 1]; j++) {
14672 checkpt = sdest(shperverlist[j]);
14673 if (pointmark(checkpt) == endpts[1]) {
14674 searchsh = shperverlist[j];
14677 checkpt = sapex(shperverlist[j]);
14678 if (pointmark(checkpt) == endpts[1]) {
14679 senext2(shperverlist[j], searchsh);
14680 sesymself(searchsh);
14686 if (searchsh.sh != NULL) {
14688 sspivot(searchsh, checkseg);
14689 if (checkseg.sh != NULL) {
14694 pa = sorg(searchsh);
14695 pb = sdest(searchsh);
14696 makeshellface(subsegs, &newseg);
14697 setshvertices(newseg, pa, pb, NULL);
14698 ssbond(searchsh, newseg);
14699 spivot(searchsh, neighsh);
14700 if (neighsh.sh != NULL) {
14701 ssbond(neighsh, newseg);
14707 pa = idx2verlist[endpts[0]];
14708 pb = idx2verlist[endpts[1]];
14711 printf(
"Warning: Edge #%d is degenerated. Skipped.\n", i);
14718 subsegs->traversalinit();
14719 segloop.sh = shellfacetraverse(subsegs);
14720 while (segloop.sh != NULL) {
14721 ppt = (point *) &(segloop.sh[3]);
14722 if (((ppt[0] == pa) && (ppt[1] == pb)) ||
14723 ((ppt[0] == pb) && (ppt[1] == pa))) {
14728 segloop.sh = shellfacetraverse(subsegs);
14730 if (newseg.sh == NULL) {
14731 makeshellface(subsegs, &newseg);
14732 setshvertices(newseg, pa, pb, NULL);
14736 setshellmark(newseg, edgemarker);
14738 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
14739 for (i = 0; i < in->numberofsegmentconstraints; i++) {
14740 e1 = (int) in->segmentconstraintlist[i * 3];
14741 e2 = (
int) in->segmentconstraintlist[i * 3 + 1];
14742 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
14743 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
14744 len = in->segmentconstraintlist[i * 3 + 2];
14745 setareabound(newseg, len);
14752 delete [] shperverlist;
14753 delete [] idx2shlist;
14762 void tetgenmesh::mergefacets()
14764 face parentsh, neighsh, neineish;
14766 point pa, pb, pc, pd;
14768 REAL cosang, cosang_tol;
14772 arraypool *dihedangarray =
new arraypool(
sizeof(
double), 10);
14773 REAL *paryang = NULL;
14777 cosang_tol = cos(b->facet_separate_ang_tol / 180.0 * PI);
14779 subsegs->traversalinit();
14780 segloop.sh = shellfacetraverse(subsegs);
14781 while (segloop.sh != (shellface *) NULL) {
14783 if (shellmark(segloop) != -1) {
14784 segloop.sh = shellfacetraverse(subsegs);
14787 spivot(segloop, parentsh);
14788 if (parentsh.sh != NULL) {
14789 spivot(parentsh, neighsh);
14790 if (neighsh.sh != NULL) {
14791 spivot(neighsh, neineish);
14792 if (neineish.sh == parentsh.sh) {
14795 if (shellmark(parentsh) == shellmark(neighsh)) {
14796 pa = sorg(segloop);
14797 pb = sdest(segloop);
14798 pc = sapex(parentsh);
14799 pd = sapex(neighsh);
14801 facenormal(pa, pb, pc, n1, 1, NULL);
14802 facenormal(pa, pb, pd, n2, 1, NULL);
14803 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14804 if (cosang < cosang_tol) {
14805 ssdissolve(parentsh);
14806 ssdissolve(neighsh);
14807 shellfacedealloc(subsegs, segloop.sh);
14809 flipshpush(&parentsh);
14813 dihedangarray->newindex((
void **) &paryang);
14815 segloop.sh[6] = (shellface) paryang;
14821 segloop.sh = shellfacetraverse(subsegs);
14826 cosang_tol = cos(b->facet_small_ang_tol / 180.0 * PI);
14827 REAL cosang_sep_tol = cos((b->facet_separate_ang_tol - 5.0) / 180.0 * PI);
14830 REAL cosang1, cosang2;
14833 subfaces->traversalinit();
14834 shloop.sh = shellfacetraverse(subfaces);
14835 while (shloop.sh != (shellface *) NULL) {
14836 for (i = 0; i < 3; i++) {
14837 if (isshsubseg(shloop)) {
14838 senext(shloop, neighsh);
14839 if (isshsubseg(neighsh)) {
14843 pb = sdest(shloop);
14844 pc = sapex(shloop);
14845 for (j = 0; j < 3; j++) n1[j] = pa[j] - pb[j];
14846 for (j = 0; j < 3; j++) n2[j] = pc[j] - pb[j];
14847 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
14848 if (cosang > cosang_tol) {
14851 sspivot(shloop, seg1);
14852 sspivot(neighsh, seg2);
14853 if (seg1.sh[6] != NULL) {
14854 paryang = (REAL *) (seg1.sh[6]);
14855 cosang1 = *paryang;
14859 if (seg2.sh[6] != NULL) {
14860 paryang = (REAL *) (seg2.sh[6]);
14861 cosang2 = *paryang;
14865 if (cosang1 < cosang_sep_tol) {
14866 if (cosang2 < cosang_sep_tol) {
14867 if (cosang1 < cosang2) {
14876 if (cosang2 < cosang_sep_tol) {
14880 if (segloop.sh != NULL) {
14883 spivot(segloop, parentsh);
14884 spivot(parentsh, neighsh);
14885 ssdissolve(parentsh);
14886 ssdissolve(neighsh);
14887 shellfacedealloc(subsegs, segloop.sh);
14889 flipshpush(&parentsh);
14895 senextself(shloop);
14897 shloop.sh = shellfacetraverse(subfaces);
14900 delete dihedangarray;
14902 if (flipstack != NULL) {
14913 void tetgenmesh::meshsurface()
14915 arraypool *ptlist, *conlist;
14916 point *idx2verlist;
14917 point tstart, tend, *pnewpt, *cons;
14924 printf(
"Creating surface mesh ...\n");
14928 makeindex2pointmap(idx2verlist);
14931 ptlist =
new arraypool(
sizeof(point *), 8);
14932 conlist =
new arraypool(2 *
sizeof(point *), 8);
14935 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
14938 f = &in->facetlist[shmark - 1];
14943 if (dupverts > 0l) {
14945 for (i = 0; i < f->numberofpolygons; i++) {
14946 p = &(f->polygonlist[i]);
14948 for (j = 0; j < p->numberofvertices; j++) {
14949 end1 = p->vertexlist[j];
14950 tstart = idx2verlist[end1];
14951 if (pointtype(tstart) == DUPLICATEDVERTEX) {
14953 tend = point2ppt(tstart);
14954 end2 = pointmark(tend);
14955 p->vertexlist[j] = end2;
14962 for (i = 0; i < f->numberofpolygons; i++) {
14964 p = &(f->polygonlist[i]);
14966 end1 = p->vertexlist[0];
14967 if ((end1 < in->firstnumber) ||
14968 (end1 >= in->firstnumber + in->numberofpoints)) {
14970 printf(
"Warning: Invalid the 1st vertex %d of polygon", end1);
14971 printf(
" %d in facet %d.\n", i + 1, shmark);
14975 tstart = idx2verlist[end1];
14977 if (!pinfected(tstart)) {
14979 ptlist->newindex((
void **) &pnewpt);
14983 for (j = 1; j <= p->numberofvertices; j++) {
14985 if (j < p->numberofvertices) {
14986 end2 = p->vertexlist[j];
14988 end2 = p->vertexlist[0];
14990 if ((end2 < in->firstnumber) ||
14991 (end2 >= in->firstnumber + in->numberofpoints)) {
14993 printf(
"Warning: Invalid vertex %d in polygon %d", end2, i + 1);
14994 printf(
" in facet %d.\n", shmark);
14997 if (end1 != end2) {
14999 tend = idx2verlist[end2];
15001 if (!pinfected(tend)) {
15003 ptlist->newindex((
void **) &pnewpt);
15007 conlist->newindex((
void **) &cons);
15015 if (p->numberofvertices > 2) {
15019 printf(
"Warning: Polygon %d has two identical verts", i + 1);
15020 printf(
" in facet %d.\n", shmark);
15027 if (p->numberofvertices == 2)
break;
15031 for (i = 0; i < ptlist->objects; i++) {
15032 pnewpt = (point *) fastlookup(ptlist, i);
15033 puninfect(*pnewpt);
15038 triangulate(in->facetmarkerlist ? in->facetmarkerlist[shmark - 1] : -1,
15039 ptlist, conlist, f->numberofholes, f->holelist);
15043 conlist->restart();
15046 if (!b->diagnose) {
15049 if (in->numberofedges > 0) {
15051 identifyinputedges(idx2verlist);
15053 if (!b->psc && !b->nomergefacet &&
15054 (!b->nobisect || (b->nobisect && !b->nobisect_nomerge))) {
15060 if (b->object == tetgenbehavior::STL) {
15066 printf(
" %ld (%ld) subfaces (segments).\n", subfaces->items,
15071 insegments = subsegs->items;
15073 delete [] idx2verlist;
15102 void tetgenmesh::interecursive(shellface** subfacearray,
int arraysize,
15103 int axis, REAL bxmin, REAL bxmax, REAL bymin,
15104 REAL bymax, REAL bzmin, REAL bzmax,
15107 shellface **leftarray, **rightarray;
15108 face sface1, sface2;
15111 enum interresult intersect;
15113 bool toleft, toright;
15114 int leftsize, rightsize;
15117 if (b->verbose > 2) {
15118 printf(
" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
15119 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
15120 axis == 0 ?
"x" : (axis == 1 ?
"y" :
"z"));
15123 leftarray =
new shellface*[arraysize];
15124 if (leftarray == NULL) {
15125 terminatetetgen(
this, 1);
15127 rightarray =
new shellface*[arraysize];
15128 if (rightarray == NULL) {
15129 terminatetetgen(
this, 1);
15131 leftsize = rightsize = 0;
15135 split = 0.5 * (bxmin + bxmax);
15136 }
else if (axis == 1) {
15138 split = 0.5 * (bymin + bymax);
15141 split = 0.5 * (bzmin + bzmax);
15144 for (i = 0; i < arraysize; i++) {
15145 sface1.sh = subfacearray[i];
15146 p1 = (point) sface1.sh[3];
15147 p2 = (point) sface1.sh[4];
15148 p3 = (point) sface1.sh[5];
15149 toleft = toright =
false;
15150 if (p1[axis] < split) {
15152 if (p2[axis] >= split || p3[axis] >= split) {
15155 }
else if (p1[axis] > split) {
15157 if (p2[axis] <= split || p3[axis] <= split) {
15166 leftarray[leftsize] = sface1.sh;
15170 rightarray[rightsize] = sface1.sh;
15175 if (leftsize < arraysize && rightsize < arraysize) {
15180 delete [] subfacearray;
15183 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
15184 bzmin, bzmax, internum);
15185 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
15186 bzmin, bzmax, internum);
15187 }
else if (axis == 1) {
15188 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
15189 bzmin, bzmax, internum);
15190 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
15191 bzmin, bzmax, internum);
15193 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
15194 bzmin, split, internum);
15195 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
15196 split, bzmax, internum);
15199 if (b->verbose > 1) {
15200 printf(
" Checking intersecting faces.\n");
15203 for (i = 0; i < arraysize; i++) {
15204 sface1.sh = subfacearray[i];
15205 p1 = (point) sface1.sh[3];
15206 p2 = (point) sface1.sh[4];
15207 p3 = (point) sface1.sh[5];
15208 for (j = i + 1; j < arraysize; j++) {
15209 sface2.sh = subfacearray[j];
15210 p4 = (point) sface2.sh[3];
15211 p5 = (point) sface2.sh[4];
15212 p6 = (point) sface2.sh[5];
15213 intersect = (
enum interresult) tri_tri_inter(p1, p2, p3, p4, p5, p6);
15214 if (intersect == INTERSECT || intersect == SHAREFACE) {
15216 if (intersect == INTERSECT) {
15217 printf(
" Facet #%d intersects facet #%d at triangles:\n",
15218 shellmark(sface1), shellmark(sface2));
15219 printf(
" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
15220 pointmark(p1), pointmark(p2), pointmark(p3),
15221 pointmark(p4), pointmark(p5), pointmark(p6));
15223 printf(
" Facet #%d duplicates facet #%d at triangle:\n",
15224 shellmark(sface1), shellmark(sface2));
15225 printf(
" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
15226 pointmark(p1), pointmark(p2), pointmark(p3),
15227 pointmark(p4), pointmark(p5), pointmark(p6));
15239 delete [] leftarray;
15240 delete [] rightarray;
15241 delete [] subfacearray;
15270 void tetgenmesh::detectinterfaces()
15272 shellface **subfacearray;
15278 printf(
"Detecting self-intersecting facets...\n");
15282 subfacearray =
new shellface*[subfaces->items];
15283 subfaces->traversalinit();
15284 shloop.sh = shellfacetraverse(subfaces);
15286 while (shloop.sh != (shellface *) NULL) {
15287 subfacearray[i] = shloop.sh;
15288 shloop.sh = shellfacetraverse(subfaces);
15296 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
15297 zmin, zmax, &internum);
15300 if (internum > 0) {
15301 printf(
"\n!! Found %d pairs of faces are intersecting.\n\n", internum);
15303 printf(
"\nNo faces are intersecting.\n\n");
15307 if (internum > 0) {
15311 subfaces->traversalinit();
15312 shloop.sh = shellfacetraverse(subfaces);
15313 while (shloop.sh != (shellface *) NULL) {
15314 if (sinfected(shloop)) {
15317 shellfacedealloc(subfaces, shloop.sh);
15319 shloop.sh = shellfacetraverse(subfaces);
15323 subfaces->restart();
15345 void tetgenmesh::makesegmentendpointsmap()
15347 arraypool *segptlist;
15348 face segloop, prevseg, nextseg;
15349 point eorg, edest, *parypt;
15350 int segindex = 0, idx = 0;
15353 if (b->verbose > 0) {
15354 printf(
" Creating the segment-endpoints map.\n");
15357 segptlist =
new arraypool(2 *
sizeof(point), 10);
15361 subsegs->traversalinit();
15362 segloop.sh = shellfacetraverse(subsegs);
15364 while (segloop.sh != NULL) {
15365 senext2(segloop, prevseg);
15366 spivotself(prevseg);
15367 if (prevseg.sh == NULL) {
15368 eorg = sorg(segloop);
15369 edest = sdest(segloop);
15370 setfacetindex(segloop, segindex);
15371 senext(segloop, nextseg);
15372 spivotself(nextseg);
15373 while (nextseg.sh != NULL) {
15374 setfacetindex(nextseg, segindex);
15376 if (sorg(nextseg) != edest) sesymself(nextseg);
15377 edest = sdest(nextseg);
15379 senextself(nextseg);
15380 spivotself(nextseg);
15382 segptlist->newindex((
void **) &parypt);
15387 segloop.sh = shellfacetraverse(subsegs);
15391 printf(
" Found %ld segments.\n", segptlist->objects);
15394 segmentendpointslist =
new point[segptlist->objects * 2];
15396 totalworkmemory += (segptlist->objects * 2) *
sizeof(point *);
15398 for (i = 0; i < segptlist->objects; i++) {
15399 parypt = (point *) fastlookup(segptlist, i);
15400 segmentendpointslist[idx++] = parypt[0];
15401 segmentendpointslist[idx++] = parypt[1];
15425 enum tetgenmesh::interresult
15426 tetgenmesh::finddirection(triface* searchtet, point endpt)
15429 point pa, pb, pc, pd;
15430 enum {HMOVE, RMOVE, LMOVE} nextmove;
15431 REAL hori, rori, lori;
15436 pa = org(*searchtet);
15437 if ((point) searchtet->tet[7] == dummypoint) {
15439 decode(searchtet->tet[3], *searchtet);
15441 if ((point) searchtet->tet[4] == pa) {
15442 searchtet->ver = 11;
15443 }
else if ((point) searchtet->tet[5] == pa) {
15444 searchtet->ver = 3;
15445 }
else if ((point) searchtet->tet[6] == pa) {
15446 searchtet->ver = 7;
15448 searchtet->ver = 0;
15452 pb = dest(*searchtet);
15459 pc = apex(*searchtet);
15462 eprevesymself(*searchtet);
15469 pd = oppo(*searchtet);
15473 esymself(*searchtet);
15474 enextself(*searchtet);
15478 if (pd == dummypoint) {
15483 terminatetetgen(
this, 2);
15492 hori = orient3d(pa, pb, pc, endpt);
15493 rori = orient3d(pb, pa, pd, endpt);
15494 lori = orient3d(pa, pc, pd, endpt);
15502 s = randomnation(3);
15505 }
else if (s == 1) {
15512 if (randomnation(2)) {
15521 if (randomnation(2)) {
15535 if (randomnation(2)) {
15557 eprevesymself(*searchtet);
15566 esymself(*searchtet);
15567 enextself(*searchtet);
15571 esymself(*searchtet);
15572 enextself(*searchtet);
15577 eprevesymself(*searchtet);
15587 if (nextmove == RMOVE) {
15588 fnextself(*searchtet);
15589 }
else if (nextmove == LMOVE) {
15590 eprevself(*searchtet);
15591 fnextself(*searchtet);
15592 enextself(*searchtet);
15594 fsymself(*searchtet);
15595 enextself(*searchtet);
15597 pb = dest(*searchtet);
15598 pc = apex(*searchtet);
15622 #pragma GCC diagnostic push 15623 #pragma GCC diagnostic ignored "-Wunused-parameter" 15624 enum tetgenmesh::interresult tetgenmesh::scoutsegment(point startpt,point endpt,
15625 face *sedge, triface* searchtet, point* refpt, arraypool* intfacelist)
15628 enum interresult dir;
15631 if (b->verbose > 2) {
15632 printf(
" Scout seg (%d, %d).\n",pointmark(startpt),pointmark(endpt));
15635 point2tetorg(startpt, *searchtet);
15636 dir = finddirection(searchtet, endpt);
15638 if (dir == ACROSSVERT) {
15639 pd = dest(*searchtet);
15641 if (issubseg(*searchtet)) {
15642 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15647 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15653 enextesymself(*searchtet);
15654 fsymself(*searchtet);
15656 if (dir == ACROSSEDGE) {
15658 if (issubseg(*searchtet)) {
15659 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15661 }
else if (dir == ACROSSFACE) {
15662 if (checksubfaceflag) {
15664 if (issubface(*searchtet)) {
15665 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15669 terminatetetgen(
this, 2);
15672 if (refpt == NULL) {
15677 triface neightet, reftet;
15680 int types[2], poss[4];
15683 pa = org(*searchtet);
15684 angmax = interiorangle(pa, startpt, endpt, NULL);
15686 pb = dest(*searchtet);
15687 ang = interiorangle(pb, startpt, endpt, NULL);
15688 if (ang > angmax) {
15692 pc = apex(*searchtet);
15693 ang = interiorangle(pc, startpt, endpt, NULL);
15694 if (ang > angmax) {
15698 reftet = *searchtet;
15704 pd = oppo(*searchtet);
15708 if (pd == endpt)
break;
15710 ang = interiorangle(pd, startpt, endpt, NULL);
15711 if (ang > angmax) {
15714 reftet = *searchtet;
15718 if (dir == ACROSSFACE) {
15720 neightet = *searchtet;
15721 j = (neightet.ver & 3);
15722 for (i = j + 1; i < j + 4; i++) {
15723 neightet.ver = (i % 4);
15724 pa = org(neightet);
15725 pb = dest(neightet);
15726 pc = apex(neightet);
15727 pd = oppo(neightet);
15728 if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
15729 dir = (
enum interresult) types[0];
15737 }
else if (dir == ACROSSEDGE) {
15739 for (i = 0; i < 2; i++) {
15741 enextesym(*searchtet, neightet);
15743 eprevesym(*searchtet, neightet);
15745 pa = org(neightet);
15746 pb = dest(neightet);
15747 pc = apex(neightet);
15748 pd = oppo(neightet);
15749 if (tri_edge_test(pa, pb, pc, startpt, endpt, pd, 1, types, poss)) {
15750 dir = (
enum interresult) types[0];
15758 if (dir == DISJOINT) {
15761 fnextself(*searchtet);
15766 if (dir == ACROSSVERT) {
15768 for (i = 0; i < pos; i++) {
15769 enextself(neightet);
15771 eprev(neightet, *searchtet);
15773 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15775 }
else if (dir == ACROSSEDGE) {
15777 for (i = 0; i < pos; i++) {
15778 enextself(neightet);
15782 fsym(neightet, *searchtet);
15784 if (dir == ACROSSEDGE) {
15786 if (issubseg(*searchtet)) {
15787 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15789 }
else if (dir == ACROSSFACE) {
15790 if (checksubfaceflag) {
15792 if (issubface(*searchtet)) {
15793 report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
15797 terminatetetgen(
this, 2);
15804 if (2.0 * angmax < PI) {
15809 *searchtet = reftet;
15812 #pragma GCC diagnostic pop 15823 int tetgenmesh::getsteinerptonsegment(face* seg, point refpt, point steinpt)
15825 point ei = sorg(*seg);
15826 point ej = sdest(*seg);
15827 int adjflag = 0, i;
15829 if (refpt != NULL) {
15832 if (pointtype(refpt) == FREESEGVERTEX) {
15834 sdecode(point2sh(refpt), parentseg);
15835 int sidx1 = getfacetindex(parentseg);
15836 point far_pi = segmentendpointslist[sidx1 * 2];
15837 point far_pj = segmentendpointslist[sidx1 * 2 + 1];
15838 int sidx2 = getfacetindex(*seg);
15839 point far_ei = segmentendpointslist[sidx2 * 2];
15840 point far_ej = segmentendpointslist[sidx2 * 2 + 1];
15841 if ((far_pi == far_ei) || (far_pj == far_ei)) {
15845 L = distance(far_ei, far_ej);
15846 L1 = distance(far_ei, refpt);
15848 for (i = 0; i < 3; i++) {
15849 steinpt[i] = far_ei[i] + t * (far_ej[i] - far_ei[i]);
15852 }
else if ((far_pi == far_ej) || (far_pj == far_ej)) {
15853 L = distance(far_ei, far_ej);
15854 L1 = distance(far_ej, refpt);
15856 for (i = 0; i < 3; i++) {
15857 steinpt[i] = far_ej[i] + t * (far_ei[i] - far_ej[i]);
15862 projpt2edge(refpt, ei, ej, steinpt);
15866 projpt2edge(refpt, ei, ej, steinpt);
15870 L = distance(ei, ej);
15871 L1 = distance(steinpt, ei);
15873 if ((t < 0.2) || (t > 0.8)) {
15875 for (i = 0; i < 3; i++) {
15876 steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]);
15881 for (i = 0; i < 3; i++) {
15882 steinpt[i] = ei[i] + 0.5 * (ej[i] - ei[i]);
15906 void tetgenmesh::delaunizesegments()
15908 triface searchtet, spintet;
15911 point refpt, newpt;
15912 enum interresult dir;
15913 insertvertexflags ivf;
15918 ivf.sloc = (int) ONEDGE;
15920 ivf.assignmeshsize = b->metric;
15921 ivf.smlenflag = useinsertradius;
15924 while (subsegstack->objects > 0l) {
15926 subsegstack->objects--;
15927 psseg = (face *) fastlookup(subsegstack, subsegstack->objects);
15931 sstpivot1(sseg, searchtet);
15932 if (searchtet.tet != NULL) {
15937 dir = scoutsegment(sorg(sseg), sdest(sseg), &sseg,&searchtet,&refpt,NULL);
15939 if (dir == SHAREEDGE) {
15942 sstbond1(sseg, searchtet);
15944 spintet = searchtet;
15946 tssbond1(spintet, sseg);
15947 fnextself(spintet);
15948 }
while (spintet.tet != searchtet.tet);
15950 if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) {
15953 makepoint(&newpt, FREESEGVERTEX);
15955 getsteinerptonsegment(&sseg, refpt, newpt);
15958 ivf.iloc = (int) OUTSIDE;
15962 if (insertpoint(newpt, &searchtet, &searchsh, &sseg, &ivf)) {
15965 if (steinerleft > 0) steinerleft--;
15966 if (useinsertradius) {
15967 save_segmentpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
15970 if (ivf.iloc == (
int) NEARVERTEX) {
15973 point nearpt = org(searchtet);
15974 if (pointtype(nearpt) == FREESEGVERTEX) {
15976 sdecode(point2sh(nearpt), parentseg);
15977 point p1 = farsorg(sseg);
15978 point p2 = farsdest(sseg);
15979 point p3 = farsorg(parentseg);
15980 point p4 = farsdest(parentseg);
15981 printf(
"Two segments are very close to each other.\n");
15982 printf(
" Segment 1: [%d, %d] #%d\n", pointmark(p1),
15983 pointmark(p2), shellmark(sseg));
15984 printf(
" Segment 2: [%d, %d] #%d\n", pointmark(p3),
15985 pointmark(p4), shellmark(parentseg));
15986 terminatetetgen(
this, 4);
15988 terminatetetgen(
this, 2);
15990 }
else if (ivf.iloc == (
int) ONVERTEX) {
15993 eprevself(searchtet);
15994 report_selfint_edge(sorg(sseg), sdest(sseg), &sseg, &searchtet,
15998 terminatetetgen(
this, 2);
16003 terminatetetgen(
this, 2);
16022 int tetgenmesh::scoutsubface(face* searchsh, triface* searchtet,
int shflag)
16024 point pa = sorg(*searchsh);
16025 point pb = sdest(*searchsh);
16028 point2tetorg(pa, *searchtet);
16030 enum interresult dir = finddirection(searchtet, pb);
16031 if (dir == ACROSSVERT) {
16033 if (dest(*searchtet) != pb) {
16036 report_selfint_edge(pa, pb, searchsh, searchtet, dir);
16038 terminatetetgen(
this, 2);
16043 point pc = sapex(*searchsh);
16045 triface spintet = *searchtet;
16047 if (apex(spintet) == pc) {
16049 if (!issubface(spintet)) {
16051 tsbond(spintet, *searchsh);
16053 sesymself(*searchsh);
16054 tsbond(spintet, *searchsh);
16055 *searchtet = spintet;
16058 terminatetetgen(
this, 2);
16061 fnextself(spintet);
16062 if (spintet.tet == searchtet->tet)
break;
16088 void tetgenmesh::formregion(face* missh, arraypool* missingshs,
16089 arraypool* missingshbds, arraypool* missingshverts)
16091 triface searchtet, spintet;
16092 face neighsh, *parysh;
16093 face neighseg, fakeseg;
16094 point pa, pb, *parypt;
16095 enum interresult dir;
16100 missingshs->newindex((
void **) &parysh);
16104 for (i = 0; i < missingshs->objects; i++) {
16105 missh = (face *) fastlookup(missingshs, i);
16106 for (j = 0; j < 3; j++) {
16108 pb = sdest(*missh);
16109 point2tetorg(pa, searchtet);
16110 dir = finddirection(&searchtet, pb);
16111 if (dir != ACROSSVERT) {
16113 spivot(*missh, neighsh);
16114 if (!smarktested(neighsh)) {
16116 if (sorg(neighsh) != pb) sesymself(neighsh);
16117 smarktest(neighsh);
16118 missingshs->newindex((
void **) &parysh);
16122 if (dest(searchtet) != pb) {
16124 report_selfint_edge(pa, pb, missh, &searchtet, dir);
16128 if (!pmarktested(pa)) {
16130 missingshverts->newindex((
void **) &parypt);
16133 senextself(*missh);
16138 for (i = 0; i < missingshs->objects; i++) {
16139 missh = (face *) fastlookup(missingshs, i);
16140 for (j = 0; j < 3; j++) {
16141 spivot(*missh, neighsh);
16142 if ((neighsh.sh == NULL) || !smarktested(neighsh)) {
16145 point2tetorg(sorg(*missh), searchtet);
16146 finddirection(&searchtet, sdest(*missh));
16147 missingshbds->newindex((
void **) &parysh);
16150 sspivot(*missh, neighseg);
16151 if (neighseg.sh == NULL) {
16153 makeshellface(subsegs, &fakeseg);
16154 setsorg(fakeseg, sorg(*missh));
16155 setsdest(fakeseg, sdest(*missh));
16158 spintet = searchtet;
16160 tssbond1(spintet, fakeseg);
16161 fnextself(spintet);
16162 if (spintet.tet == searchtet.tet)
break;
16164 neighseg = fakeseg;
16167 ssbond(*missh, neighseg);
16168 sstbond1(neighseg, searchtet);
16170 senextself(*missh);
16176 for (i = 0; i < missingshs->objects; i++) {
16177 parysh = (face *) fastlookup(missingshs, i);
16178 sunmarktest(*parysh);
16194 int tetgenmesh::scoutcrossedge(triface& crosstet, arraypool* missingshbds,
16195 arraypool* missingshs)
16197 triface searchtet, spintet, neightet;
16198 face oldsh, searchsh, *parysh;
16200 point pa, pb, pc, pd, pe;
16202 int types[2], poss[4];
16203 int searchflag, interflag;
16210 for (i = 0; i < missingshbds->objects && !searchflag; i++) {
16211 parysh = (face *) fastlookup(missingshbds, i);
16212 sspivot(*parysh, neighseg);
16213 sstpivot1(neighseg, searchtet);
16214 if (org(searchtet) != sorg(*parysh)) {
16215 esymself(searchtet);
16217 spintet = searchtet;
16219 if (pmarktested(apex(spintet))) {
16221 neightet = spintet;
16224 for (j = 0; j < 2; j++) {
16225 enextself(neightet);
16226 if (!issubseg(neightet)) {
16228 senext(oldsh, searchsh);
16230 senext2(oldsh, searchsh);
16231 sesymself(searchsh);
16232 esymself(neightet);
16235 pa = sorg(searchsh);
16236 pb = sdest(searchsh);
16237 pc = sapex(searchsh);
16238 pd = dest(neightet);
16239 calculateabovepoint4(pa, pb, pc, pd);
16241 ori = orient3d(pa, pb, pc, dummypoint);
16243 sesymself(searchsh);
16244 senextself(searchsh);
16245 }
else if (ori == 0) {
16246 terminatetetgen(
this, 2);
16248 if (sscoutsegment(&searchsh,dest(neightet),0,0,1)==SHAREEDGE) {
16251 makeshellface(subsegs, &tmpseg);
16252 ssbond(searchsh, tmpseg);
16253 spivotself(searchsh);
16254 ssbond(searchsh, tmpseg);
16258 spivot(tmpseg, searchsh);
16259 ssdissolve(searchsh);
16260 spivotself(searchsh);
16261 ssdissolve(searchsh);
16262 shellfacedealloc(subsegs, tmpseg.sh);
16266 if (flipstack != NULL) {
16273 if (searchflag)
break;
16275 fnextself(spintet);
16276 if (spintet.tet == searchtet.tet)
break;
16285 for (i = 0; i < missingshs->objects; i++) {
16286 parysh = (face *) fastlookup(missingshs, i);
16288 for (j = 0; j < 3; j++) {
16289 if (isshsubseg(oldsh)) {
16290 sspivot(oldsh, checkseg);
16291 if (sinfected(checkseg)) {
16293 sstpivot1(checkseg, searchtet);
16294 spintet = searchtet;
16296 tssdissolve1(spintet);
16297 fnextself(spintet);
16298 if (spintet.tet == searchtet.tet)
break;
16300 shellfacedealloc(subsegs, checkseg.sh);
16315 for (j = 0; j < missingshbds->objects && (searchflag == -1); j++) {
16316 parysh = (face *) fastlookup(missingshbds, j);
16317 sspivot(*parysh, neighseg);
16318 sstpivot1(neighseg, searchtet);
16321 spintet = searchtet;
16323 pd = apex(spintet);
16324 pe = oppo(spintet);
16326 if ((pd != dummypoint) && (pe != dummypoint)) {
16328 if (!pmarktested(pd) && !pmarktested(pe)) {
16330 for (i = 0; i < missingshs->objects && !interflag; i++) {
16331 parysh = (face *) fastlookup(missingshs, i);
16332 pa = sorg(*parysh);
16333 pb = sdest(*parysh);
16334 pc = sapex(*parysh);
16335 interflag=tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss);
16336 if (interflag > 0) {
16337 if (interflag == 2) {
16339 if ((types[0] == (
int) ACROSSFACE) ||
16340 (types[0] == (
int) ACROSSEDGE)) {
16342 edestoppo(spintet, crosstet);
16343 if (issubseg(crosstet)) {
16345 report_selfint_face(pa, pb, pc, parysh, &crosstet,
16346 interflag, types, poss);
16348 triface chkface = crosstet;
16350 if (issubface(chkface))
break;
16352 if (chkface.tet == crosstet.tet)
break;
16354 if (issubface(chkface)) {
16356 report_selfint_face(pa, pb, pc, parysh, &chkface,
16357 interflag, types, poss);
16361 ori = orient3d(pa, pb, pc, pd);
16363 esymself(crosstet);
16370 report_selfint_face(pa, pb, pc, parysh, &crosstet,
16371 interflag, types, poss);
16380 if (interflag > 0)
break;
16382 fnextself(spintet);
16383 if (spintet.tet == searchtet.tet)
break;
16413 bool tetgenmesh::formcavity(triface* searchtet, arraypool* missingshs,
16414 arraypool* crosstets, arraypool* topfaces,
16415 arraypool* botfaces, arraypool* toppoints,
16416 arraypool* botpoints)
16418 arraypool *crossedges;
16419 triface spintet, neightet, chkface, *parytet;
16420 face *parysh = NULL;
16421 point pa, pd, pe, *parypt;
16422 bool testflag, invalidflag;
16423 int intflag, types[2], poss[4];
16428 crossedges = topfaces;
16430 if (b->verbose > 2) {
16431 printf(
" Form the cavity of a missing region.\n");
16434 markedge(*searchtet);
16435 crossedges->newindex((
void **) &parytet);
16436 *parytet = *searchtet;
16442 for (i = 0; i < crossedges->objects && !invalidflag; i++) {
16444 searchtet = (triface *) fastlookup(crossedges, i);
16446 pd = org(*searchtet);
16447 if (!pinfected(pd)) {
16449 botpoints->newindex((
void **) &parypt);
16452 pe = dest(*searchtet);
16453 if (!pinfected(pe)) {
16455 toppoints->newindex((
void **) &parypt);
16460 spintet = *searchtet;
16462 if (!infected(spintet)) {
16464 crosstets->newindex((
void **) &parytet);
16465 *parytet = spintet;
16468 fnextself(spintet);
16469 if (spintet.tet == searchtet->tet)
break;
16473 spintet = *searchtet;
16476 pa = apex(spintet);
16477 if (pa != dummypoint) {
16478 if (!pmarktested(pa)) {
16483 for (j = 0; j < 2 && testflag; j++) {
16485 enext(spintet, neightet);
16487 eprev(spintet, neightet);
16490 if (edgemarked(neightet)) {
16495 fnextself(neightet);
16496 if (neightet.tet == spintet.tet)
break;
16504 pe = dest(spintet);
16505 for (k = 0; k < missingshs->objects; k++) {
16506 parysh = (face *) fastlookup(missingshs, k);
16507 intflag = tri_edge_test(sorg(*parysh), sdest(*parysh),
16508 sapex(*parysh), pe, pa, NULL, 1, types, poss);
16511 if (intflag == 2) {
16512 enext(spintet, neightet);
16513 if ((types[0] == (
int) ACROSSFACE) ||
16514 (types[0] == (
int) ACROSSEDGE)) {
16526 intflag = tri_edge_test(sorg(*parysh), sdest(*parysh),
16527 sapex(*parysh), pa, pd, NULL, 1, types, poss);
16530 if (intflag == 2) {
16531 eprev(spintet, neightet);
16532 if ((types[0] == (
int) ACROSSFACE) ||
16533 (types[0] == (
int) ACROSSEDGE)) {
16546 if (k < missingshs->objects) {
16553 esymself(neightet);
16555 if (issubseg(neightet)) {
16556 report_selfint_face(sorg(*parysh), sdest(*parysh),
16557 sapex(*parysh),parysh,&neightet,intflag,types,poss);
16560 chkface = neightet;
16562 if (issubface(chkface))
break;
16564 if (chkface.tet == neightet.tet)
break;
16566 if (issubface(chkface)) {
16568 report_selfint_face(sorg(*parysh), sdest(*parysh),
16569 sapex(*parysh),parysh,&chkface,intflag,types,poss);
16573 markedge(neightet);
16574 crossedges->newindex((
void **) &parytet);
16575 *parytet = neightet;
16585 fnextself(spintet);
16586 if (spintet.tet == searchtet->tet)
break;
16591 for (i = 0; i < crossedges->objects; i++) {
16592 searchtet = (triface *) fastlookup(crossedges, i);
16593 unmarkedge(*searchtet);
16595 crossedges->restart();
16600 for (i = 0; i < crosstets->objects; i++) {
16601 searchtet = (triface *) fastlookup(crosstets, i);
16602 uninfect(*searchtet);
16605 for (i = 0; i < botpoints->objects; i++) {
16606 parypt = (point *) fastlookup(botpoints, i);
16607 puninfect(*parypt);
16609 for (i = 0; i < toppoints->objects; i++) {
16610 parypt = (point *) fastlookup(toppoints, i);
16611 puninfect(*parypt);
16613 crosstets->restart();
16614 botpoints->restart();
16615 toppoints->restart();
16618 i = randomnation(missingshs->objects - 1);
16619 recentsh = * (face *) fastlookup(missingshs, i);
16623 if (b->verbose > 2) {
16624 printf(
" Formed cavity: %ld (%ld) cross tets (edges).\n",
16625 crosstets->objects, crossedges->objects);
16641 for (i = 0; i < crosstets->objects; i++) {
16642 searchtet = (triface *) fastlookup(crosstets, i);
16644 eorgoppo(*searchtet, spintet);
16645 fsym(spintet, neightet);
16646 if (!infected(neightet)) {
16648 topfaces->newindex((
void **) &parytet);
16649 *parytet = neightet;
16651 edestoppo(*searchtet, spintet);
16652 fsym(spintet, neightet);
16653 if (!infected(neightet)) {
16655 botfaces->newindex((
void **) &parytet);
16656 *parytet = neightet;
16659 pa = org(neightet);
16660 if (!pinfected(pa)) {
16661 if (pa != dummypoint) {
16663 botpoints->newindex((
void **) &parypt);
16665 toppoints->newindex((
void **) &parypt);
16669 pa = dest(neightet);
16670 if (!pinfected(pa)) {
16671 if (pa != dummypoint) {
16673 botpoints->newindex((
void **) &parypt);
16675 toppoints->newindex((
void **) &parypt);
16682 for (i = 0; i < toppoints->objects; i++) {
16683 parypt = (point *) fastlookup(toppoints, i);
16684 puninfect(*parypt);
16686 for (i = 0; i < botpoints->objects; i++) {
16687 parypt = (point *) fastlookup(botpoints, i);
16688 puninfect(*parypt);
16712 void tetgenmesh::delaunizecavity(arraypool *cavpoints, arraypool *cavfaces,
16713 arraypool *cavshells, arraypool *newtets,
16714 arraypool *crosstets, arraypool *misfaces)
16716 triface searchtet, neightet, *parytet, *parytet1;
16717 face tmpsh, *parysh;
16718 point pa, pb, pc, pd, pt[3], *parypt;
16719 insertvertexflags ivf;
16721 long baknum, bakhullsize;
16722 int bakchecksubsegflag, bakchecksubfaceflag;
16726 if (b->verbose > 2) {
16727 printf(
" Delaunizing cavity: %ld points, %ld faces.\n",
16728 cavpoints->objects, cavfaces->objects);
16731 baknum = crosstets->objects;
16732 bakhullsize = hullsize;
16733 bakchecksubsegflag = checksubsegflag;
16734 bakchecksubfaceflag = checksubfaceflag;
16736 checksubsegflag = 0;
16737 checksubfaceflag = 0;
16744 pa = pb = pc = NULL;
16745 for (i = 0; i < cavfaces->objects; i++) {
16746 parytet = (triface *) fastlookup(cavfaces, i);
16747 parytet->ver = epivot[parytet->ver];
16748 if (apex(*parytet) != dummypoint) {
16749 pa = org(*parytet);
16750 pb = dest(*parytet);
16751 pc = apex(*parytet);
16756 for (; i < cavfaces->objects; i++) {
16757 parytet = (triface *) fastlookup(cavfaces, i);
16758 pt[0] = org(*parytet);
16759 pt[1] = dest(*parytet);
16760 pt[2] = apex(*parytet);
16761 for (j = 0; j < 3; j++) {
16762 if (pt[j] != dummypoint) {
16763 ori = orient3d(pa, pb, pc, pt[j]);
16767 pt[j] = pa; pa = pb; pb = pt[j];
16773 if (pd != NULL)
break;
16777 initialdelaunay(pa, pb, pc, pd);
16780 for (i = 0; i < cavpoints->objects; i++) {
16781 pt[0] = * (point *) fastlookup(cavpoints, i);
16782 searchtet = recenttet;
16783 ivf.iloc = (int) OUTSIDE;
16784 insertpoint(pt[0], &searchtet, NULL, NULL, &ivf);
16787 if (b->verbose > 2) {
16788 printf(
" Identifying %ld boundary faces of the cavity.\n",
16789 cavfaces->objects);
16795 for (i = 0; i < cavfaces->objects; i++) {
16796 parytet = (triface *) fastlookup(cavfaces, i);
16798 if (infected(*parytet))
continue;
16799 parytet->ver = epivot[parytet->ver];
16800 pt[0] = org(*parytet);
16801 pt[1] = dest(*parytet);
16802 pt[2] = apex(*parytet);
16804 makeshellface(subfaces, &tmpsh);
16805 setshvertices(tmpsh, pt[0], pt[1], pt[2]);
16807 searchtet.tet = NULL;
16808 if (scoutsubface(&tmpsh, &searchtet, 0)) {
16812 tmpsh.sh[0] = (shellface) encode(*parytet);
16814 cavshells->newindex((
void **) &parysh);
16819 shellfacedealloc(subfaces, tmpsh.sh);
16821 misfaces->newindex((
void **) &parytet1);
16822 *parytet1 = *parytet;
16826 if (misfaces->objects > 0) {
16827 if (b->verbose > 2) {
16828 printf(
" Enlarging the cavity. %ld missing bdry faces\n",
16829 misfaces->objects);
16833 for (i = 0; i < cavshells->objects; i++) {
16834 parysh = (face *) fastlookup(cavshells, i);
16835 stpivot(*parysh, neightet);
16836 tsdissolve(neightet);
16837 fsymself(neightet);
16838 tsdissolve(neightet);
16839 shellfacedealloc(subfaces, parysh->sh);
16841 cavshells->restart();
16844 for (i = 0; i < cavpoints->objects; i++) {
16845 pt[0] = * (point *) fastlookup(cavpoints, i);
16850 for (i = 0; i < misfaces->objects; i++) {
16852 parytet = (triface *) fastlookup(misfaces, i);
16853 if (!infected(*parytet)) {
16856 crosstets->newindex((
void **) &parytet1);
16857 *parytet1 = *parytet;
16859 pd = oppo(*parytet);
16860 if (!pinfected(pd)) {
16861 searchtet = recenttet;
16862 ivf.iloc = (int) OUTSIDE;
16863 insertpoint(pd, &searchtet, NULL, NULL, &ivf);
16865 cavpoints->newindex((
void **) &parypt);
16869 for (j = 0; j < 3; j++) {
16870 esym(*parytet, neightet);
16871 fsymself(neightet);
16872 if (!infected(neightet)) {
16873 cavfaces->newindex((
void **) &parytet1);
16874 *parytet1 = neightet;
16876 enextself(*parytet);
16882 for (i = 0; i < cavpoints->objects; i++) {
16883 pt[0] = * (point *) fastlookup(cavpoints, i);
16887 misfaces->restart();
16896 marktest(recenttet);
16897 newtets->newindex((
void **) &parytet);
16898 *parytet = recenttet;
16899 for (i = 0; i < newtets->objects; i++) {
16900 searchtet = * (triface *) fastlookup(newtets, i);
16901 for (j = 0; j < 4; j++) {
16902 decode(searchtet.tet[j], neightet);
16903 if (!marktested(neightet)) {
16904 marktest(neightet);
16905 newtets->newindex((
void **) &parytet);
16906 *parytet = neightet;
16911 cavpoints->restart();
16912 cavfaces->restart();
16914 if (crosstets->objects > baknum) {
16920 hullsize = bakhullsize;
16921 checksubsegflag = bakchecksubsegflag;
16922 checksubfaceflag = bakchecksubfaceflag;
16940 bool tetgenmesh::fillcavity(arraypool* topshells, arraypool* botshells,
16941 arraypool* midfaces, arraypool* missingshs,
16942 arraypool* topnewtets, arraypool* botnewtets,
16943 triface* crossedge)
16945 arraypool *cavshells;
16946 triface bdrytet, neightet, *parytet;
16947 triface searchtet, spintet;
16957 for (j = 0; j < 2; j++) {
16958 cavshells = (j == 0 ? topshells : botshells);
16959 if (cavshells != NULL) {
16960 for (i = 0; i < cavshells->objects; i++) {
16962 parysh = (face *) fastlookup(cavshells, i);
16964 decode(parysh->sh[0], bdrytet);
16966 pb = dest(bdrytet);
16967 pc = apex(bdrytet);
16969 stpivot(*parysh, neightet);
16973 bond(bdrytet, neightet);
16974 tsdissolve(neightet);
16976 setpoint2tet(pa, (tetrahedron) neightet.tet);
16977 setpoint2tet(pb, (tetrahedron) neightet.tet);
16978 setpoint2tet(pc, (tetrahedron) neightet.tet);
16983 if (crossedge != NULL) {
16985 triface toptet, bottet, spintet, *midface;
16988 int types[2], poss[4];
16993 pd = org(*crossedge);
16994 pe = dest(*crossedge);
17001 for (i = 0; i < topnewtets->objects && !mflag; i++) {
17002 searchtet = * (triface *) fastlookup(topnewtets, i);
17003 for (searchtet.ver = 0; searchtet.ver < 4 && !mflag; searchtet.ver++) {
17004 pa = org(searchtet);
17005 if (pmarktested(pa)) {
17006 pb = dest(searchtet);
17007 if (pmarktested(pb)) {
17008 pc = apex(searchtet);
17009 if (pmarktested(pc)) {
17011 interflag = tri_edge_test(pa,pb,pc,pd,pe,NULL,1,types,poss);
17012 if (interflag == 2) {
17014 toptet = searchtet;
17017 ori = orient3d(pa, pb, pc, pd);
17022 }
else if (ori == 0) {
17023 terminatetetgen(
this, 2);
17026 for (j = 0; j < botnewtets->objects; j++) {
17027 neightet = * (triface *) fastlookup(botnewtets, j);
17029 if ((point) neightet.tet[4] == pb) {
17031 }
else if ((point) neightet.tet[5] == pb) {
17033 }
else if ((point) neightet.tet[6] == pb) {
17035 }
else if ((point) neightet.tet[7] == pb) {
17041 if (dest(neightet) == pa) {
17043 }
else if (apex(neightet) == pa) {
17044 eprevesymself(neightet);
17045 }
else if (oppo(neightet) == pa) {
17046 esymself(neightet);
17047 enextself(neightet);
17052 if (apex(neightet) == pc) {
17067 bond(toptet, bottet);
17073 midfaces->newindex((
void **) &parytet);
17079 i = randomnation(missingshs->objects - 1);
17080 recentsh = * (face *) fastlookup(missingshs, i);
17084 for (i = 0; i < midfaces->objects && mflag; i++) {
17086 midface = (triface *) fastlookup(midfaces, i);
17088 for (j = 0; j < 3 && mflag; j++) {
17095 if (pmarktested(pc)) {
17098 if (pc == dummypoint) {
17099 terminatetetgen(
this, 2);
17105 if (!marktested(toptet)) {
17107 bflag =
true;
break;
17111 if (!facemarked(toptet)) {
17112 fsym(*midface, bottet);
17117 if (pd == pc)
break;
17119 if (bottet.tet == spintet.tet) {
17126 if (marktested(bottet)) {
17128 bond(toptet, bottet);
17134 midfaces->newindex((
void **) &parytet);
17139 terminatetetgen(
this, 2);
17143 fsym(*midface, bottet);
17148 if (pmarktested(pd)) {
17153 ori = orient3d(dest(toptet), pc, oppo(toptet), pd);
17158 }
else if (ori > 0) {
17164 terminatetetgen(
this, 2);
17173 enextself(*midface);
17178 if (b->verbose > 2) {
17179 printf(
" Found %ld middle subfaces.\n", midfaces->objects);
17181 face oldsh, newsh, casout, casin, neighsh;
17183 oldsh = * (face *) fastlookup(missingshs, 0);
17186 for (i = 0; i < midfaces->objects; i++) {
17188 midface = (triface *) fastlookup(midfaces, i);
17189 unmarkface(*midface);
17190 makeshellface(subfaces, &newsh);
17191 setsorg(newsh, org(*midface));
17192 setsdest(newsh, dest(*midface));
17193 setsapex(newsh, apex(*midface));
17195 setshellmark(newsh, shellmark(oldsh));
17196 if (checkconstraints) {
17197 setareabound(newsh, areabound(oldsh));
17199 if (useinsertradius) {
17200 setfacetindex(newsh, getfacetindex(oldsh));
17203 tsbond(*midface, newsh);
17204 fsym(*midface, neightet);
17206 tsbond(neightet, newsh);
17211 for (i = 0; i < midfaces->objects; i++) {
17213 midface = (triface *) fastlookup(midfaces, i);
17214 for (j = 0; j < 3; j++) {
17215 tspivot(*midface, newsh);
17216 spivot(newsh, casout);
17217 if (casout.sh == NULL) {
17219 fnext(*midface, searchtet);
17222 tsspivot1(searchtet, checkseg);
17223 if (checkseg.sh != NULL) {
17226 checkseg.shver = 0;
17227 spivot(checkseg, oldsh);
17228 if (sinfected(checkseg)) {
17230 spintet = searchtet;
17232 tssdissolve1(spintet);
17233 fnextself(spintet);
17234 if (spintet.tet == searchtet.tet)
break;
17236 shellfacedealloc(subsegs, checkseg.sh);
17238 checkseg.sh = NULL;
17240 spivot(oldsh, casout);
17241 if (casout.sh != NULL) {
17243 if (checkseg.sh != NULL) {
17246 checkseg.shver = 0;
17247 if (sorg(newsh) != sorg(checkseg)) {
17250 spivot(casin, neighsh);
17251 while (neighsh.sh != oldsh.sh) {
17253 spivot(casin, neighsh);
17256 sbond1(newsh, casout);
17257 sbond1(casin, newsh);
17259 if (checkseg.sh != NULL) {
17260 ssbond(newsh, checkseg);
17265 tspivot(searchtet, neighsh);
17266 if (neighsh.sh != NULL) {
17268 sbond(newsh, neighsh);
17271 fnextself(searchtet);
17274 enextself(*midface);
17279 for (i = 0; i < missingshs->objects; i++) {
17280 parysh = (face *) fastlookup(missingshs, i);
17281 shellfacedealloc(subfaces, parysh->sh);
17284 if (toptet.tet != NULL) {
17296 for (i = 1; i < missingshs->objects; i++) {
17297 parysh = (face *) fastlookup(missingshs, i);
17298 if (((sorg(*parysh) == pa) && (sdest(*parysh) == pb)) ||
17299 ((sorg(*parysh) == pb) && (sdest(*parysh) == pa)))
break;
17300 if (((sorg(*parysh) == pc) && (sdest(*parysh) == pd)) ||
17301 ((sorg(*parysh) == pd) && (sdest(*parysh) == pc)))
break;
17303 if (i < missingshs->objects) {
17305 recentsh = *parysh;
17307 terminatetetgen(
this, 2);
17314 midfaces->restart();
17320 for (j = 0; j < 2; j++) {
17321 cavshells = (j == 0 ? topshells : botshells);
17322 if (cavshells != NULL) {
17323 for (i = 0; i < cavshells->objects; i++) {
17324 parysh = (face *) fastlookup(cavshells, i);
17325 shellfacedealloc(subfaces, parysh->sh);
17330 topshells->restart();
17331 if (botshells != NULL) {
17332 botshells->restart();
17344 void tetgenmesh::carvecavity(arraypool *crosstets, arraypool *topnewtets,
17345 arraypool *botnewtets)
17347 arraypool *newtets;
17348 shellface *sptr, *ssptr;
17349 triface *parytet, *pnewtet, newtet, neightet, spintet;
17350 face checksh, *parysh;
17351 face checkseg, *paryseg;
17355 if (b->verbose > 2) {
17356 printf(
" Carve cavity: %ld old tets.\n", crosstets->objects);
17367 for (i = 0; i < crosstets->objects; i++) {
17368 parytet = (triface *) fastlookup(crosstets, i);
17369 if ((sptr = (shellface*) parytet->tet[9]) != NULL) {
17370 for (j = 0; j < 4; j++) {
17372 sdecode(sptr[j], checksh);
17373 if (!sinfected(checksh)) {
17375 cavetetshlist->newindex((
void **) &parysh);
17381 if ((ssptr = (shellface*) parytet->tet[8]) != NULL) {
17382 for (j = 0; j < 6; j++) {
17384 sdecode(ssptr[j], checkseg);
17386 if (checkseg.sh[3] != NULL) {
17387 if (!sinfected(checkseg)) {
17389 cavetetseglist->newindex((
void **) &paryseg);
17390 *paryseg = checkseg;
17399 for (i = 0; i < cavetetshlist->objects; i++) {
17400 parysh = (face *) fastlookup(cavetetshlist, i);
17401 suninfect(*parysh);
17404 for (i = 0; i < cavetetseglist->objects; i++) {
17405 paryseg = (face *) fastlookup(cavetetseglist, i);
17406 suninfect(*paryseg);
17410 for (i = 0; i < cavetetshlist->objects; i++) {
17411 parysh = (face *) fastlookup(cavetetshlist, i);
17413 stpivot(*parysh, neightet);
17415 if (infected(neightet)) {
17417 sesymself(*parysh);
17418 stpivot(*parysh, neightet);
17420 if (infected(neightet)) {
17422 stdissolve(checksh);
17423 caveencshlist->newindex((
void **) &parysh);
17427 if (!infected(neightet)) {
17429 fsym(neightet, newtet);
17430 sesymself(*parysh);
17431 tsbond(newtet, *parysh);
17436 for (i = 0; i < cavetetseglist->objects; i++) {
17437 checkseg = * (face *) fastlookup(cavetetseglist, i);
17439 sstpivot1(checkseg, neightet);
17440 spintet = neightet;
17442 if (!infected(spintet)) {
17446 fnextself(spintet);
17447 if (spintet.tet == neightet.tet) {
17448 sstdissolve1(checkseg);
17449 caveencseglist->newindex((
void **) &paryseg);
17450 *paryseg = checkseg;
17454 if (!infected(spintet)) {
17456 sstbond1(checkseg, spintet);
17457 neightet = spintet;
17459 tssbond1(spintet, checkseg);
17460 fnextself(spintet);
17461 if (spintet.tet == neightet.tet)
break;
17467 cavetetshlist->restart();
17468 cavetetseglist->restart();
17471 for (i = 0; i < crosstets->objects; i++) {
17472 parytet = (triface *) fastlookup(crosstets, i);
17473 if (ishulltet(*parytet)) {
17476 tetrahedrondealloc(parytet->tet);
17479 crosstets->restart();
17483 for (j = 0; j < 2; j++) {
17484 newtets = (j == 0 ? topnewtets : botnewtets);
17485 if (newtets != NULL) {
17486 for (i = 0; i < newtets->objects; i++) {
17487 parytet = (triface *) fastlookup(newtets, i);
17488 if (infected(*parytet)) {
17489 crosstets->newindex((
void **) &pnewtet);
17490 *pnewtet = *parytet;
17497 for (i = 0; i < crosstets->objects; i++) {
17498 parytet = (triface *) fastlookup(crosstets, i);
17499 for (j = 0; j < 4; j++) {
17500 decode(parytet->tet[j], neightet);
17501 if (marktested(neightet)) {
17502 if (!infected(neightet)) {
17506 crosstets->newindex((
void **) &pnewtet);
17507 *pnewtet = neightet;
17513 parytet = (triface *) fastlookup(crosstets, 0);
17514 recenttet = *parytet;
17517 for (j = 0; j < 2; j++) {
17518 newtets = (j == 0 ? topnewtets : botnewtets);
17519 if (newtets != NULL) {
17520 for (i = 0; i < newtets->objects; i++) {
17521 parytet = (triface *) fastlookup(newtets, i);
17522 if (infected(*parytet)) {
17524 uninfect(*parytet);
17525 unmarktest(*parytet);
17526 if (ishulltet(*parytet)) {
17531 tetrahedrondealloc(parytet->tet);
17537 crosstets->restart();
17538 topnewtets->restart();
17539 if (botnewtets != NULL) {
17540 botnewtets->restart();
17550 void tetgenmesh::restorecavity(arraypool *crosstets, arraypool *topnewtets,
17551 arraypool *botnewtets, arraypool *missingshbds)
17553 triface *parytet, neightet, spintet;
17561 for (i = 0; i < crosstets->objects; i++) {
17562 parytet = (triface *) fastlookup(crosstets, i);
17564 for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) {
17565 fsym(*parytet, neightet);
17566 if (!infected(neightet)) {
17568 bond(*parytet, neightet);
17573 ppt = (point *) &(parytet->tet[4]);
17574 for (j = 0; j < 4; j++) {
17575 setpoint2tet(ppt[j], encode(*parytet));
17580 for (i = 0; i < crosstets->objects; i++) {
17581 parytet = (triface *) fastlookup(crosstets, i);
17582 uninfect(*parytet);
17586 if (crosstets->objects > 0) {
17587 recenttet = * (triface *) fastlookup(crosstets, 0);
17591 for (i = 0; i < missingshbds->objects; i++) {
17592 parysh = (face *) fastlookup(missingshbds, i);
17593 sspivot(*parysh, checkseg);
17594 if (checkseg.sh[3] != NULL) {
17595 if (sinfected(checkseg)) {
17597 sstpivot1(checkseg, neightet);
17598 spintet = neightet;
17600 tssdissolve1(spintet);
17601 fnextself(spintet);
17602 if (spintet.tet == neightet.tet)
break;
17604 shellfacedealloc(subsegs, checkseg.sh);
17605 ssdissolve(*parysh);
17612 for (i = 0; i < topnewtets->objects; i++) {
17613 parytet = (triface *) fastlookup(topnewtets, i);
17614 tetrahedrondealloc(parytet->tet);
17617 if (botnewtets != NULL) {
17618 for (i = 0; i < botnewtets->objects; i++) {
17619 parytet = (triface *) fastlookup(botnewtets, i);
17620 tetrahedrondealloc(parytet->tet);
17624 crosstets->restart();
17625 topnewtets->restart();
17626 if (botnewtets != NULL) {
17627 botnewtets->restart();
17640 void tetgenmesh::flipcertify(triface *chkface,badface **pqueue,point plane_pa,
17641 point plane_pb, point plane_pc)
17643 badface *parybf, *prevbf, *nextbf;
17653 fsym(*chkface, neightet);
17655 p[0] = org(*chkface);
17656 p[1] = dest(*chkface);
17657 p[2] = apex(*chkface);
17658 p[3] = oppo(*chkface);
17659 p[4] = oppo(neightet);
17663 for (i = 0; i < 3; i++) {
17664 if (pmarktest2ed(p[i])) topi++;
17665 if (pmarktest3ed(p[i])) boti++;
17667 if ((topi == 0) || (boti == 0)) {
17670 for (i = 3; i < 5; i++) {
17671 if (pmarktest2ed(p[i])) topi++;
17672 if (pmarktest3ed(p[i])) boti++;
17674 if ((topi == 0) || (boti == 0)) {
17677 if ((p[3] != dummypoint) && (p[4] != dummypoint)) {
17679 tspivot(*chkface, checksh);
17680 if (checksh.sh == NULL) {
17681 insph = insphere_s(p[1], p[0], p[2], p[3], p[4]);
17684 if (b->verbose > 2) {
17685 printf(
" A locally non-Delanay face (%d, %d, %d)-%d,%d\n",
17686 pointmark(p[0]), pointmark(p[1]), pointmark(p[2]),
17687 pointmark(p[3]), pointmark(p[4]));
17689 parybf = (badface *) flippool->alloc();
17691 parybf->tt = *chkface;
17692 parybf->forg = p[0];
17693 parybf->fdest = p[1];
17694 parybf->fapex = p[2];
17695 parybf->foppo = p[3];
17696 parybf->noppo = p[4];
17698 if (*pqueue == NULL) {
17700 parybf->nextitem = NULL;
17702 parybf->nextitem = *pqueue;
17713 for (i = 0; i < 5; i++) {
17714 if (pmarktest2ed(p[i])) {
17716 w[i] = orient3dfast(plane_pa, plane_pb, plane_pc, p[i]);
17717 if (w[i] < 0) w[i] = -w[i];
17723 insph = insphere(p[1], p[0], p[2], p[3], p[4]);
17724 ori4 = orient4d(p[1], p[0], p[2], p[3], p[4], w[1], w[0], w[2], w[3], w[4]);
17727 if (b->verbose > 2) {
17728 printf(
" Insert face (%d, %d, %d) - %d, %d\n", pointmark(p[0]),
17729 pointmark(p[1]), pointmark(p[2]), pointmark(p[3]), pointmark(p[4]));
17732 parybf = (badface *) flippool->alloc();
17734 parybf->key = -insph / ori4;
17735 parybf->tt = *chkface;
17736 parybf->forg = p[0];
17737 parybf->fdest = p[1];
17738 parybf->fapex = p[2];
17739 parybf->foppo = p[3];
17740 parybf->noppo = p[4];
17744 if (*pqueue == NULL) {
17746 parybf->nextitem = NULL;
17753 while (nextbf != NULL) {
17754 if (nextbf->key < parybf->key) {
17756 nextbf = nextbf->nextitem;
17763 if (prevbf == NULL) {
17766 prevbf->nextitem = parybf;
17768 parybf->nextitem = nextbf;
17770 }
else if (ori4 == 0) {
17789 void tetgenmesh::flipinsertfacet(arraypool *crosstets, arraypool *toppoints,
17790 arraypool *botpoints, arraypool *midpoints)
17792 arraypool *crossfaces, *bfacearray;
17793 triface fliptets[6], baktets[2], fliptet, newface;
17794 triface neightet, *parytet;
17796 badface *popbf, bface;
17797 point plane_pa, plane_pb, plane_pc;
17798 point p1, p2, pd, pe;
17800 flipconstraints fc;
17802 int convcount, copcount;
17803 int flipflag, fcount;
17805 long f23count, f32count, f44count;
17808 f23count = flip23count;
17809 f32count = flip32count;
17810 f44count = flip44count;
17813 calculateabovepoint(midpoints, &plane_pa, &plane_pb, &plane_pc);
17816 for (i = 0; i < toppoints->objects; i++) {
17817 parypt = (point *) fastlookup(toppoints, i);
17818 if (!pmarktested(*parypt)) {
17819 pmarktest2(*parypt);
17822 for (i = 0; i < botpoints->objects; i++) {
17823 parypt = (point *) fastlookup(botpoints, i);
17824 if (!pmarktested(*parypt)) {
17825 pmarktest3(*parypt);
17830 crossfaces = cavetetlist;
17834 for (i = 0; i < crosstets->objects; i++) {
17835 parytet = (triface *) fastlookup(crosstets, i);
17836 fliptet = *parytet;
17837 for (fliptet.ver = 0; fliptet.ver < 4; fliptet.ver++) {
17838 fsym(fliptet, neightet);
17839 if (infected(neightet)) {
17840 if (!marktested(neightet)) {
17841 crossfaces->newindex((
void **) &parytet);
17842 *parytet = fliptet;
17849 if (b->verbose > 1) {
17850 printf(
" Found %ld crossing faces.\n", crossfaces->objects);
17853 for (i = 0; i < crosstets->objects; i++) {
17854 parytet = (triface *) fastlookup(crosstets, i);
17855 unmarktest(*parytet);
17856 uninfect(*parytet);
17862 for (i = 0; i < crossfaces->objects; i++) {
17863 parytet = (triface *) fastlookup(crossfaces, i);
17864 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
17866 crossfaces->restart();
17869 bfacearray =
new arraypool(
sizeof(triface), 4);
17875 while (pqueue != NULL) {
17881 pqueue = pqueue->nextitem;
17883 flippool->dealloc((
void *) popbf);
17885 if (!isdeadtet(bface.tt)) {
17886 if ((org(bface.tt) == bface.forg) && (dest(bface.tt) == bface.fdest) &&
17887 (apex(bface.tt) == bface.fapex) && (oppo(bface.tt) == bface.foppo)) {
17889 fliptet = bface.tt;
17890 fsym(fliptet, neightet);
17891 if (oppo(neightet) == bface.noppo) {
17892 pd = oppo(fliptet);
17893 pe = oppo(neightet);
17895 if (b->verbose > 2) {
17896 printf(
" Get face (%d, %d, %d) - %d, %d, tau = %.17g\n",
17897 pointmark(bface.forg), pointmark(bface.fdest),
17898 pointmark(bface.fapex), pointmark(bface.foppo),
17899 pointmark(bface.noppo), bface.key);
17906 for (i = 0; i < 3; i++) {
17908 p2 = dest(fliptet);
17909 ori[i] = orient3d(p1, p2, pd, pe);
17913 }
else if (ori[i] == 0) {
17918 enextself(fliptet);
17921 if (convcount == 3) {
17923 fliptets[0] = fliptet;
17924 fliptets[1] = neightet;
17925 flip23(fliptets, 1, &fc);
17927 for (i = 0; i < 3; i++) {
17928 eprevesym(fliptets[i], newface);
17929 crossfaces->newindex((
void **) &parytet);
17930 *parytet = newface;
17932 for (i = 0; i < 3; i++) {
17933 enextesym(fliptets[i], newface);
17934 crossfaces->newindex((
void **) &parytet);
17935 *parytet = newface;
17938 }
else if (convcount == 2) {
17942 for (i = 0; i < 3; i++) {
17943 if (ori[i] <= 0)
break;
17944 enextself(fliptet);
17948 esym(fliptet, fliptets[0]);
17951 p1 = apex(fliptets[n]);
17952 if (!(pmarktested(p1) || pmarktest2ed(p1) || pmarktest3ed(p1))) {
17957 fnext(fliptets[n], fliptets[n + 1]);
17959 }
while ((fliptets[n].tet != fliptet.tet) && (n < 5));
17963 flip32(fliptets, 1, &fc);
17965 for (i = 0; i < 3; i++) {
17966 esym(fliptets[0], newface);
17967 crossfaces->newindex((
void **) &parytet);
17968 *parytet = newface;
17969 enextself(fliptets[0]);
17971 for (i = 0; i < 3; i++) {
17972 esym(fliptets[1], newface);
17973 crossfaces->newindex((
void **) &parytet);
17974 *parytet = newface;
17975 enextself(fliptets[1]);
17978 }
else if (n == 4) {
17979 if (copcount == 1) {
17992 fliptets[0] = fliptet;
17994 baktets[0] = fliptets[2];
17995 baktets[1] = fliptets[3];
17997 flip23(fliptets, 1, &fc);
18001 for (i = 1; i < 3; i++) {
18002 eprevesym(fliptets[i], newface);
18003 crossfaces->newindex((
void **) &parytet);
18004 *parytet = newface;
18006 for (i = 1; i < 3; i++) {
18007 enextesym(fliptets[i], newface);
18008 crossfaces->newindex((
void **) &parytet);
18009 *parytet = newface;
18012 enextesymself(fliptets[0]);
18013 eprevself(fliptets[0]);
18014 fliptets[1] = baktets[0];
18015 fliptets[2] = baktets[1];
18016 flip32(fliptets, 1, &fc);
18021 enextself(fliptets[0]);
18022 for (i = 1; i < 3; i++) {
18023 esym(fliptets[0], newface);
18024 crossfaces->newindex((
void **) &parytet);
18025 *parytet = newface;
18026 enextself(fliptets[0]);
18028 enextself(fliptets[1]);
18029 for (i = 1; i < 3; i++) {
18030 esym(fliptets[1], newface);
18031 crossfaces->newindex((
void **) &parytet);
18032 *parytet = newface;
18033 enextself(fliptets[1]);
18044 if (b->verbose > 2) {
18045 printf(
" Ignore face (%d, %d, %d) - %d, %d, tau = %.17g\n",
18046 pointmark(bface.forg), pointmark(bface.fdest),
18047 pointmark(bface.fapex), pointmark(bface.foppo),
18048 pointmark(bface.noppo), bface.key);
18052 if (flipflag == 1) {
18054 for (i = 0; i < crossfaces->objects; i++) {
18055 parytet = (triface *) fastlookup(crossfaces, i);
18056 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
18058 crossfaces->restart();
18061 for (i = 0; i < bfacearray->objects; i++) {
18062 parytet = (triface *) fastlookup(bfacearray, i);
18064 if (!isdeadtet(*parytet)) {
18065 flipcertify(parytet, &pqueue, plane_pa, plane_pb, plane_pc);
18068 bfacearray->restart();
18071 }
else if (flipflag == 0) {
18073 bfacearray->newindex((
void **) &parytet);
18074 *parytet = fliptet;
18082 if (bfacearray->objects > 0) {
18084 printf(
"!! No flip is found in %ld faces.\n", bfacearray->objects);
18085 terminatetetgen(
this, 2);
18092 for (i = 0; i < toppoints->objects; i++) {
18093 parypt = (point *) fastlookup(toppoints, i);
18094 punmarktest2(*parypt);
18096 for (i = 0; i < botpoints->objects; i++) {
18097 parypt = (point *) fastlookup(botpoints, i);
18098 punmarktest3(*parypt);
18101 f23count = flip23count - f23count;
18102 f32count = flip32count - f32count;
18103 f44count = flip44count - f44count;
18104 totalfcount = f23count + f32count + f44count;
18105 if (b->verbose > 2) {
18106 printf(
" Total %ld flips. f23(%ld), f32(%ld), f44(%ld).\n",
18107 totalfcount, f23count, f32count, f44count);
18117 int tetgenmesh::insertpoint_cdt(point newpt, triface *searchtet, face *splitsh,
18118 face *splitseg, insertvertexflags *ivf,
18119 arraypool *cavpoints, arraypool *cavfaces,
18120 arraypool *cavshells, arraypool *newtets,
18121 arraypool *crosstets, arraypool *misfaces)
18123 triface neightet, *parytet;
18124 face checksh, *parysh, *parysh1;
18125 face *paryseg, *paryseg1;
18130 if (b->verbose > 2) {
18131 printf(
" Insert point %d into CDT\n", pointmark(newpt));
18134 if (!insertpoint(newpt, searchtet, NULL, NULL, ivf)) {
18140 for (i = 0; i < cavetetvertlist->objects; i++) {
18141 cavpoints->newindex((
void **) &parypt);
18142 *parypt = * (point *) fastlookup(cavetetvertlist, i);
18145 cavpoints->newindex((
void **) &parypt);
18148 for (i = 0; i < cavebdrylist->objects; i++) {
18149 cavfaces->newindex((
void **) &parytet);
18150 *parytet = * (triface *) fastlookup(cavebdrylist, i);
18153 for (i = 0; i < caveoldtetlist->objects; i++) {
18154 crosstets->newindex((
void **) &parytet);
18155 *parytet = * (triface *) fastlookup(caveoldtetlist, i);
18158 cavetetvertlist->restart();
18159 cavebdrylist->restart();
18160 caveoldtetlist->restart();
18163 delaunizecavity(cavpoints, cavfaces, cavshells, newtets, crosstets,
18165 fillcavity(cavshells, NULL, NULL, NULL, NULL, NULL, NULL);
18166 carvecavity(crosstets, newtets, NULL);
18168 if ((splitsh != NULL) || (splitseg != NULL)) {
18170 sinsertvertex(newpt, splitsh, splitseg, ivf->sloc, ivf->sbowywat, 0);
18173 for (i = 0; i < caveshbdlist->objects; i++) {
18175 parysh = (face *) fastlookup(caveshbdlist, i);
18176 spivot(*parysh, checksh);
18178 if (checksh.sh[3] != NULL) {
18179 subfacstack->newindex((
void **) &parysh);
18184 if (splitseg != NULL) {
18186 for (i = 0; i < cavesegshlist->objects; i++) {
18187 paryseg = (face *) fastlookup(cavesegshlist, i);
18188 subsegstack->newindex((
void **) &paryseg1);
18189 *paryseg1 = *paryseg;
18194 for (i = 0; i < caveshlist->objects; i++) {
18195 parysh = (face *) fastlookup(caveshlist, i);
18196 if (checksubfaceflag) {
18200 stpivot(*parysh, neightet);
18201 if (neightet.tet != NULL) {
18202 if (neightet.tet[4] != NULL) {
18204 tsdissolve(neightet);
18205 fsymself(neightet);
18206 tsdissolve(neightet);
18210 shellfacedealloc(subfaces, parysh->sh);
18212 if (splitseg != NULL) {
18214 shellfacedealloc(subsegs, splitseg->sh);
18218 caveshlist->restart();
18219 caveshbdlist->restart();
18220 cavesegshlist->restart();
18226 for (i = 0; i < caveencshlist->objects; i++) {
18227 parysh = (face *) fastlookup(caveencshlist, i);
18228 if (parysh->sh[3] != NULL) {
18229 subfacstack->newindex((
void **) &parysh1);
18230 *parysh1 = *parysh;
18237 for (i = 0; i < caveencseglist->objects; i++) {
18238 paryseg = (face *) fastlookup(caveencseglist, i);
18239 if (paryseg->sh[3] != NULL) {
18240 subsegstack->newindex((
void **) &paryseg1);
18241 *paryseg1 = *paryseg;
18245 caveencshlist->restart();
18246 caveencseglist->restart();
18262 void tetgenmesh::refineregion(face &splitsh, arraypool *cavpoints,
18263 arraypool *cavfaces, arraypool *cavshells,
18264 arraypool *newtets, arraypool *crosstets,
18265 arraypool *misfaces)
18267 triface searchtet, spintet;
18268 face splitseg, *paryseg;
18269 point steinpt, pa, pb, refpt;
18270 insertvertexflags ivf;
18271 enum interresult dir;
18272 long baknum = points->items;
18277 for (i = 0; i < 3; i++) {
18278 sspivot(splitsh, splitseg);
18279 if (splitseg.sh == NULL)
break;
18280 senextself(splitsh);
18283 if (b->verbose > 2) {
18284 printf(
" Refining region at edge (%d, %d, %d).\n",
18285 pointmark(sorg(splitsh)), pointmark(sdest(splitsh)),
18286 pointmark(sapex(splitsh)));
18290 pa = sorg(splitsh);
18291 pb = sdest(splitsh);
18293 makepoint(&steinpt, FREEFACETVERTEX);
18294 for (i = 0; i < 3; i++) {
18295 steinpt[i] = 0.5 * (pa[i] + pb[i]);
18300 ivf.sloc = (int) ONEDGE;
18302 ivf.assignmeshsize = b->metric;
18303 ivf.smlenflag = useinsertradius;
18305 point2tetorg(pa, searchtet);
18306 ivf.iloc = (int) OUTSIDE;
18309 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, NULL, &ivf, cavpoints,
18310 cavfaces, cavshells, newtets, crosstets, misfaces)) {
18311 if (ivf.iloc == (
int) ENCSEGMENT) {
18312 pointdealloc(steinpt);
18314 i = randomnation(encseglist->objects);
18315 paryseg = (face *) fastlookup(encseglist, i);
18316 splitseg = *paryseg;
18317 encseglist->restart();
18320 pa = sorg(splitseg);
18321 pb = sdest(splitseg);
18323 makepoint(&steinpt, FREESEGVERTEX);
18324 for (i = 0; i < 3; i++) {
18325 steinpt[i] = 0.5 * (pa[i] + pb[i]);
18327 point2tetorg(pa, searchtet);
18328 ivf.iloc = (int) OUTSIDE;
18330 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf,
18331 cavpoints, cavfaces, cavshells, newtets,
18332 crosstets, misfaces)) {
18333 terminatetetgen(
this, 2);
18335 if (useinsertradius) {
18336 save_segmentpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18339 if (steinerleft > 0) steinerleft--;
18341 terminatetetgen(
this, 2);
18344 if (useinsertradius) {
18345 save_facetpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18348 if (steinerleft > 0) steinerleft--;
18351 while (subsegstack->objects > 0l) {
18353 subsegstack->objects--;
18354 paryseg = (face *) fastlookup(subsegstack, subsegstack->objects);
18355 splitseg = *paryseg;
18358 sstpivot1(splitseg, searchtet);
18359 if (searchtet.tet != NULL)
continue;
18362 dir = scoutsegment(sorg(splitseg), sdest(splitseg), &splitseg, &searchtet,
18364 if (dir == SHAREEDGE) {
18367 sstbond1(splitseg, searchtet);
18369 spintet = searchtet;
18371 tssbond1(spintet, splitseg);
18372 fnextself(spintet);
18373 }
while (spintet.tet != searchtet.tet);
18375 if ((dir == ACROSSFACE) || (dir == ACROSSEDGE)) {
18377 makepoint(&steinpt, FREESEGVERTEX);
18378 getsteinerptonsegment(&splitseg, refpt, steinpt);
18379 ivf.iloc = (int) OUTSIDE;
18381 if (!insertpoint_cdt(steinpt, &searchtet, &splitsh, &splitseg, &ivf,
18382 cavpoints, cavfaces, cavshells, newtets,
18383 crosstets, misfaces)) {
18384 terminatetetgen(
this, 2);
18386 if (useinsertradius) {
18387 save_segmentpoint_insradius(steinpt, ivf.parentpt, ivf.smlen);
18390 if (steinerleft > 0) steinerleft--;
18392 terminatetetgen(
this, 2);
18397 if (b->verbose > 2) {
18398 printf(
" Added %ld Steiner points.\n", points->items - baknum);
18410 void tetgenmesh::constrainedfacets()
18412 arraypool *tg_crosstets, *tg_topnewtets, *tg_botnewtets;
18413 arraypool *tg_topfaces, *tg_botfaces, *tg_midfaces;
18414 arraypool *tg_topshells, *tg_botshells, *tg_facfaces;
18415 arraypool *tg_toppoints, *tg_botpoints;
18416 arraypool *tg_missingshs, *tg_missingshbds, *tg_missingshverts;
18417 triface searchtet, neightet, crossedge;
18418 face searchsh, *parysh, *parysh1;
18421 enum interresult dir;
18428 tg_crosstets =
new arraypool(
sizeof(triface), 10);
18429 tg_topnewtets =
new arraypool(
sizeof(triface), 10);
18430 tg_botnewtets =
new arraypool(
sizeof(triface), 10);
18431 tg_topfaces =
new arraypool(
sizeof(triface), 10);
18432 tg_botfaces =
new arraypool(
sizeof(triface), 10);
18433 tg_midfaces =
new arraypool(
sizeof(triface), 10);
18434 tg_toppoints =
new arraypool(
sizeof(point), 8);
18435 tg_botpoints =
new arraypool(
sizeof(point), 8);
18436 tg_facfaces =
new arraypool(
sizeof(face), 10);
18437 tg_topshells =
new arraypool(
sizeof(face), 10);
18438 tg_botshells =
new arraypool(
sizeof(face), 10);
18439 tg_missingshs =
new arraypool(
sizeof(face), 10);
18440 tg_missingshbds =
new arraypool(
sizeof(face), 10);
18441 tg_missingshverts =
new arraypool(
sizeof(point), 8);
18443 encseglist =
new arraypool(
sizeof(face), 4);
18447 while (subfacstack->objects > 0l) {
18449 subfacstack->objects--;
18450 parysh = (face *) fastlookup(subfacstack, subfacstack->objects);
18451 searchsh = *parysh;
18453 if (searchsh.sh[3] == NULL)
continue;
18454 if (isshtet(searchsh))
continue;
18457 smarktest(searchsh);
18458 tg_facfaces->newindex((
void **) &parysh);
18459 *parysh = searchsh;
18460 for (i = 0; i < tg_facfaces->objects; i++) {
18461 parysh = (face *) fastlookup(tg_facfaces, i);
18462 for (j = 0; j < 3; j++) {
18463 if (!isshsubseg(*parysh)) {
18464 spivot(*parysh, searchsh);
18465 if (!smarktested(searchsh)) {
18466 if (!isshtet(searchsh)) {
18467 smarktest(searchsh);
18468 tg_facfaces->newindex((
void **) &parysh1);
18469 *parysh1 = searchsh;
18473 senextself(*parysh);
18477 for (i = 0; i < tg_facfaces->objects; i++) {
18478 parysh = (face *) fastlookup(tg_facfaces, i);
18479 sunmarktest(*parysh);
18482 if (b->verbose > 1) {
18483 printf(
" Recovering facet #%d: %ld subfaces.\n", facetcount + 1,
18484 tg_facfaces->objects);
18488 while (tg_facfaces->objects > 0l) {
18490 tg_facfaces->objects--;
18491 parysh = (face *) fastlookup(tg_facfaces, tg_facfaces->objects);
18492 searchsh = *parysh;
18494 if (searchsh.sh[3] == NULL)
continue;
18495 if (isshtet(searchsh))
continue;
18497 searchtet.tet = NULL;
18498 if (scoutsubface(&searchsh, &searchtet, 1))
continue;
18502 formregion(&searchsh, tg_missingshs, tg_missingshbds, tg_missingshverts);
18504 int searchflag = scoutcrossedge(searchtet, tg_missingshbds, tg_missingshs);
18505 if (searchflag > 0) {
18507 crossedge = searchtet;
18509 success = formcavity(&searchtet, tg_missingshs, tg_crosstets,
18510 tg_topfaces, tg_botfaces, tg_toppoints,
18513 if (!b->flipinsert) {
18515 delaunizecavity(tg_toppoints, tg_topfaces, tg_topshells,
18516 tg_topnewtets, tg_crosstets, tg_midfaces);
18518 delaunizecavity(tg_botpoints, tg_botfaces, tg_botshells,
18519 tg_botnewtets, tg_crosstets, tg_midfaces);
18521 success = fillcavity(tg_topshells, tg_botshells, tg_midfaces,
18522 tg_missingshs, tg_topnewtets, tg_botnewtets,
18526 carvecavity(tg_crosstets, tg_topnewtets, tg_botnewtets);
18528 restorecavity(tg_crosstets, tg_topnewtets, tg_botnewtets,
18533 flipinsertfacet(tg_crosstets, tg_toppoints, tg_botpoints,
18534 tg_missingshverts);
18536 for (i = 0; i < tg_missingshs->objects; i++) {
18537 parysh = (face *) fastlookup(tg_missingshs, i);
18538 tg_facfaces->newindex((
void **) &parysh1);
18539 *parysh1 = *parysh;
18543 tg_crosstets->restart();
18544 tg_topfaces->restart();
18545 tg_botfaces->restart();
18546 tg_toppoints->restart();
18547 tg_botpoints->restart();
18552 for (i = 0; i < caveencshlist->objects; i++) {
18553 parysh = (face *) fastlookup(caveencshlist, i);
18554 if (!scoutsubface(parysh, &searchtet, 1)) {
18557 tg_facfaces->newindex((
void **) &parysh1);
18558 *parysh1 = *parysh;
18561 caveencshlist->restart();
18563 for (i = 0; i < caveencseglist->objects; i++) {
18564 paryseg = (face *) fastlookup(caveencseglist, i);
18565 dir = scoutsegment(sorg(*paryseg), sdest(*paryseg), paryseg,
18566 &searchtet, NULL, NULL);
18567 if (dir != SHAREEDGE) {
18568 terminatetetgen(
this, 2);
18572 sstbond1(*paryseg, searchtet);
18574 neightet = searchtet;
18576 tssbond1(neightet, *paryseg);
18577 fnextself(neightet);
18578 }
while (neightet.tet != searchtet.tet);
18580 caveencseglist->restart();
18584 terminatetetgen(
this, 2);
18588 for (i = 0; i < tg_missingshs->objects; i++) {
18589 parysh = (face *) fastlookup(tg_missingshs, i);
18590 tg_facfaces->newindex((
void **) &parysh1);
18591 *parysh1 = *parysh;
18593 if (searchflag != -1) {
18597 restorecavity(tg_crosstets, tg_topnewtets, tg_botnewtets,
18600 recentsh = searchsh;
18606 for (i = 0; i < tg_missingshverts->objects; i++) {
18607 parypt = (point *) fastlookup(tg_missingshverts, i);
18608 punmarktest(*parypt);
18610 tg_missingshverts->restart();
18611 tg_missingshbds->restart();
18612 tg_missingshs->restart();
18616 refineregion(recentsh, tg_toppoints, tg_topfaces, tg_topshells,
18617 tg_topnewtets, tg_crosstets, tg_midfaces);
18624 totalworkmemory += (tg_crosstets->totalmemory + tg_topnewtets->totalmemory +
18625 tg_botnewtets->totalmemory + tg_topfaces->totalmemory +
18626 tg_botfaces->totalmemory + tg_midfaces->totalmemory +
18627 tg_toppoints->totalmemory + tg_botpoints->totalmemory +
18628 tg_facfaces->totalmemory + tg_topshells->totalmemory +
18629 tg_botshells->totalmemory + tg_missingshs->totalmemory +
18630 tg_missingshbds->totalmemory +
18631 tg_missingshverts->totalmemory +
18632 encseglist->totalmemory);
18635 delete tg_crosstets;
18636 delete tg_topnewtets;
18637 delete tg_botnewtets;
18638 delete tg_topfaces;
18639 delete tg_botfaces;
18640 delete tg_midfaces;
18641 delete tg_toppoints;
18642 delete tg_botpoints;
18643 delete tg_facfaces;
18644 delete tg_topshells;
18645 delete tg_botshells;
18646 delete tg_missingshs;
18647 delete tg_missingshbds;
18648 delete tg_missingshverts;
18659 void tetgenmesh::constraineddelaunay(clock_t& tv)
18661 face searchsh, *parysh;
18662 face searchseg, *paryseg;
18666 long bakfillregioncount;
18667 long bakcavitycount, bakcavityexpcount;
18668 long bakseg_ref_count;
18671 printf(
"Constrained Delaunay...\n");
18674 makesegmentendpointsmap();
18675 makefacetverticesmap();
18678 printf(
" Delaunizing segments.\n");
18681 checksubsegflag = 1;
18684 subsegs->traversalinit();
18685 for (i = 0; i < subsegs->items; i++) {
18686 s = randomnation(i + 1);
18688 subsegstack->newindex((
void **) &paryseg);
18689 *paryseg = * (face *) fastlookup(subsegstack, s);
18691 searchseg.sh = shellfacetraverse(subsegs);
18693 paryseg = (face *) fastlookup(subsegstack, s);
18694 *paryseg = searchseg;
18698 delaunizesegments();
18701 printf(
" Inserted %ld Steiner points.\n", st_segref_count);
18707 printf(
" Constraining facets.\n");
18711 checksubfaceflag = 1;
18713 bakfillregioncount = fillregioncount;
18714 bakcavitycount = cavitycount;
18715 bakcavityexpcount = cavityexpcount;
18716 bakseg_ref_count = st_segref_count;
18719 subfaces->traversalinit();
18720 for (i = 0; i < subfaces->items; i++) {
18721 s = randomnation(i + 1);
18723 subfacstack->newindex((
void **) &parysh);
18724 *parysh = * (face *) fastlookup(subfacstack, s);
18726 searchsh.sh = shellfacetraverse(subfaces);
18727 parysh = (face *) fastlookup(subfacstack, s);
18728 *parysh = searchsh;
18732 constrainedfacets();
18735 if (fillregioncount > bakfillregioncount) {
18736 printf(
" Remeshed %ld regions.\n", fillregioncount-bakfillregioncount);
18738 if (cavitycount > bakcavitycount) {
18739 printf(
" Remeshed %ld cavities", cavitycount - bakcavitycount);
18740 if (cavityexpcount - bakcavityexpcount) {
18741 printf(
" (%ld enlarged)", cavityexpcount - bakcavityexpcount);
18745 if (st_segref_count + st_facref_count - bakseg_ref_count > 0) {
18746 printf(
" Inserted %ld (%ld, %ld) refine points.\n",
18747 st_segref_count + st_facref_count - bakseg_ref_count,
18748 st_segref_count - bakseg_ref_count, st_facref_count);
18774 int tetgenmesh::checkflipeligibility(
int fliptype, point pa, point pb,
18775 point pc, point pd, point pe,
18776 int level,
int edgepivot,
18777 flipconstraints* fc)
18780 enum interresult dir;
18781 int types[2], poss[4];
18786 if (fc->seg[0] != NULL) {
18788 if (fliptype == 1) {
18793 for (i = 0; i < 3 && !rejflag; i++) {
18794 if (tmppts[i] != dummypoint) {
18796 intflag = tri_edge_test(pe, pd, tmppts[i], fc->seg[0], fc->seg[1],
18797 NULL, 1, types, poss);
18798 if (intflag == 2) {
18800 dir = (
enum interresult) types[0];
18801 if (dir == ACROSSFACE) {
18804 }
else if (dir == ACROSSEDGE) {
18805 if (poss[0] == 0) {
18811 }
else if (intflag == 4) {
18813 dir = (
enum interresult) types[0];
18814 if (dir == ACROSSEDGE) {
18815 if (poss[0] == 0) {
18824 }
else if (fliptype == 2) {
18826 if (pc != dummypoint) {
18828 intflag = tri_edge_test(pa, pb, pc, fc->seg[0], fc->seg[1], NULL,
18830 if (intflag == 2) {
18832 dir = (
enum interresult) types[0];
18833 if (dir == ACROSSFACE) {
18837 }
else if (intflag == 4) {
18839 dir = (
enum interresult) types[0];
18840 if (dir == ACROSSEDGE) {
18849 if ((fc->fac[0] != NULL) && !rejflag) {
18851 if (fliptype == 1) {
18854 intflag = tri_edge_test(fc->fac[0], fc->fac[1], fc->fac[2], pe, pd,
18855 NULL, 1, types, poss);
18856 if (intflag == 2) {
18858 dir = (
enum interresult) types[0];
18859 if (dir == ACROSSFACE) {
18861 }
else if (dir == ACROSSEDGE) {
18864 }
else if (intflag == 4) {
18867 for (i = 0; i < 2 && !rejflag; i++) {
18868 dir = (
enum interresult) types[i];
18869 if (dir == ACROSSFACE) {
18871 }
else if (dir == ACROSSEDGE) {
18879 if ((fc->remvert != NULL) && !rejflag) {
18882 if (fliptype == 1) {
18884 if ((pd == fc->remvert) || (pe == fc->remvert)) {
18890 if (fc->remove_large_angle && !rejflag) {
18892 REAL cosmaxd = 0, diff;
18893 if (fliptype == 1) {
18898 if ((pc != dummypoint) && (pe != dummypoint) && (pd != dummypoint)) {
18900 tetalldihedral(pe, pd, pb, pc, NULL, &cosmaxd, NULL);
18901 diff = cosmaxd - fc->cosdihed_in;
18902 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18907 if (cosmaxd < fc->cosdihed_out) {
18908 fc->cosdihed_out = cosmaxd;
18911 tetalldihedral(pe, pd, pc, pa, NULL, &cosmaxd, NULL);
18912 diff = cosmaxd - fc->cosdihed_in;
18913 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18918 if (cosmaxd < fc->cosdihed_out) {
18919 fc->cosdihed_out = cosmaxd;
18924 }
else if (fliptype == 2) {
18929 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18931 tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL);
18932 diff = cosmaxd - fc->cosdihed_in;
18933 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18938 if (cosmaxd < fc->cosdihed_out) {
18939 fc->cosdihed_out = cosmaxd;
18942 tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL);
18943 diff = cosmaxd - fc->cosdihed_in;
18944 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18949 if (cosmaxd < fc->cosdihed_out) {
18950 fc->cosdihed_out = cosmaxd;
18956 if (edgepivot == 1) {
18958 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18960 tetalldihedral(pb, pa, pc, pe, NULL, &cosmaxd, NULL);
18961 diff = cosmaxd - fc->cosdihed_in;
18962 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18967 if (cosmaxd < fc->cosdihed_out) {
18968 fc->cosdihed_out = cosmaxd;
18974 if ((pa != dummypoint) && (pb != dummypoint) && (pc != dummypoint)) {
18976 tetalldihedral(pa, pb, pc, pd, NULL, &cosmaxd, NULL);
18977 diff = cosmaxd - fc->cosdihed_in;
18978 if (fabs(diff/fc->cosdihed_in) < b->epsilon) diff = 0.0;
18983 if (cosmaxd < fc->cosdihed_out) {
18984 fc->cosdihed_out = cosmaxd;
19009 int tetgenmesh::removeedgebyflips(triface *flipedge, flipconstraints* fc)
19011 triface *abtets, spintet;
19016 if (checksubsegflag) {
19018 if (issubseg(*flipedge)) {
19019 if (fc->collectencsegflag) {
19020 face checkseg, *paryseg;
19021 tsspivot1(*flipedge, checkseg);
19022 if (!sinfected(checkseg)) {
19025 caveencseglist->newindex((
void **) &paryseg);
19026 *paryseg = checkseg;
19035 spintet = *flipedge;
19038 fnextself(spintet);
19039 if (spintet.tet == flipedge->tet)
break;
19043 terminatetetgen(
this, 2);
19046 if ((b->flipstarsize > 0) && (n > b->flipstarsize)) {
19052 abtets =
new triface[n];
19054 spintet = *flipedge;
19057 abtets[i] = spintet;
19058 setelemcounter(abtets[i], 1);
19060 fnextself(spintet);
19061 if (spintet.tet == flipedge->tet)
break;
19066 nn = flipnm(abtets, n, 0, 0, fc);
19071 for (i = 0; i < nn; i++) {
19072 setelemcounter(abtets[i], 0);
19075 *flipedge = abtets[0];
19080 int bakunflip = fc->unflip;
19082 flipnm_post(abtets, n, nn, 0, fc);
19083 fc->unflip = bakunflip;
19102 int tetgenmesh::removefacebyflips(triface *flipface, flipconstraints* fc)
19104 triface fliptets[3], flipedge;
19105 point pa, pb, pc, pd, pe;
19109 fliptets[0] = *flipface;
19110 fsym(*flipface, fliptets[1]);
19111 pa = org(fliptets[0]);
19112 pb = dest(fliptets[0]);
19113 pc = apex(fliptets[0]);
19114 pd = oppo(fliptets[0]);
19115 pe = oppo(fliptets[1]);
19117 ori = orient3d(pa, pb, pd, pe);
19119 ori = orient3d(pb, pc, pd, pe);
19121 ori = orient3d(pc, pa, pd, pe);
19126 eprev(*flipface, flipedge);
19129 enext(*flipface, flipedge);
19132 flipedge = *flipface;
19137 flip23(fliptets, 0, fc);
19141 if (removeedgebyflips(&flipedge, fc) == 2) {
19170 int tetgenmesh::recoveredgebyflips(point startpt, point endpt, face *sedge,
19171 triface* searchtet,
int fullsearch)
19173 flipconstraints fc;
19174 enum interresult dir;
19176 fc.seg[0] = startpt;
19178 fc.checkflipeligibility = 1;
19184 point2tetorg(startpt, *searchtet);
19185 dir = finddirection(searchtet, endpt);
19186 if (dir == ACROSSVERT) {
19187 if (dest(*searchtet) == endpt) {
19191 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19201 enextesymself(*searchtet);
19202 if (dir == ACROSSFACE) {
19203 if (checksubfaceflag) {
19204 if (issubface(*searchtet)) {
19206 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19213 if (removefacebyflips(searchtet, &fc)) {
19216 }
else if (dir == ACROSSEDGE) {
19217 if (checksubsegflag) {
19218 if (issubseg(*searchtet)) {
19220 return report_selfint_edge(startpt, endpt, sedge, searchtet, dir);
19227 if (removeedgebyflips(searchtet, &fc) == 2) {
19236 triface neightet, spintet;
19237 point pa, pb, pc, pd;
19239 enum interresult dir1;
19240 int types[2], poss[4], pos = 0;
19247 point2tetorg(startpt, *searchtet);
19248 dir = finddirection(searchtet, endpt);
19251 enextesymself(*searchtet);
19257 fsymself(*searchtet);
19258 if (dir == ACROSSFACE) {
19259 neightet = *searchtet;
19260 j = (neightet.ver & 3);
19261 for (i = j + 1; i < j + 4; i++) {
19262 neightet.ver = (i % 4);
19263 pa = org(neightet);
19264 pb = dest(neightet);
19265 pc = apex(neightet);
19266 pd = oppo(neightet);
19267 if (tri_edge_test(pa,pb,pc,startpt,endpt, pd, 1, types, poss)) {
19268 dir = (
enum interresult) types[0];
19277 if (dir == DISJOINT) {
19278 terminatetetgen(
this, 2);
19280 }
else if (dir == ACROSSEDGE) {
19283 for (i = 0; i < 2; i++) {
19285 enextesym(*searchtet, neightet);
19287 eprevesym(*searchtet, neightet);
19289 pa = org(neightet);
19290 pb = dest(neightet);
19291 pc = apex(neightet);
19292 pd = oppo(neightet);
19293 if (tri_edge_test(pa,pb,pc,startpt,endpt,pd,1, types, poss)) {
19294 dir = (
enum interresult) types[0];
19302 if (dir != DISJOINT) {
19307 fnextself(*searchtet);
19310 terminatetetgen(
this, 2);
19314 for (i = 0; i < pos; i++) {
19315 enextself(neightet);
19318 if (dir == SHAREVERT) {
19320 pd = org(neightet);
19325 terminatetetgen(
this, 2);
19330 *searchtet = neightet;
19333 bakface.forg = org(*searchtet);
19334 bakface.fdest = dest(*searchtet);
19335 bakface.fapex = apex(*searchtet);
19336 bakface.foppo = oppo(*searchtet);
19339 if (dir == ACROSSFACE) {
19340 if (checksubfaceflag) {
19341 if (issubface(*searchtet)) {
19343 return report_selfint_edge(startpt,endpt,sedge,searchtet,dir);
19349 if (removefacebyflips(searchtet, &fc)) {
19353 }
else if (dir == ACROSSEDGE) {
19354 if (checksubsegflag) {
19355 if (issubseg(*searchtet)) {
19357 return report_selfint_edge(startpt,endpt,sedge,searchtet,dir);
19363 if (removeedgebyflips(searchtet, &fc) == 2) {
19367 }
else if (dir == ACROSSVERT) {
19370 terminatetetgen(
this, 2);
19375 terminatetetgen(
this, 2);
19379 if ((searchtet->tet == NULL) ||
19380 (org(*searchtet) != bakface.forg) ||
19381 (dest(*searchtet) != bakface.fdest) ||
19382 (apex(*searchtet) != bakface.fapex) ||
19383 (oppo(*searchtet) != bakface.foppo)) {
19385 point2tetorg(bakface.forg, *searchtet);
19386 dir1 = finddirection(searchtet, bakface.fdest);
19387 if (dir1 == ACROSSVERT) {
19388 if (dest(*searchtet) == bakface.fdest) {
19389 spintet = *searchtet;
19391 if (apex(spintet) == bakface.fapex) {
19393 *searchtet = spintet;
19396 fnextself(spintet);
19397 if (spintet.tet == searchtet->tet) {
19398 searchtet->tet = NULL;
19402 if (searchtet->tet != NULL) {
19403 if (oppo(*searchtet) != bakface.foppo) {
19404 fsymself(*searchtet);
19405 if (oppo(*searchtet) != bakface.foppo) {
19407 searchtet->tet = NULL;
19413 searchtet->tet = NULL;
19416 searchtet->tet = NULL;
19418 if (searchtet->tet == NULL) {
19454 int tetgenmesh::add_steinerpt_in_schoenhardtpoly(triface *abtets,
int n,
19457 triface worktet, *parytet;
19458 triface faketet1, faketet2;
19459 point pc, pd, steinerpt;
19460 insertvertexflags ivf;
19462 REAL vcd[3], sampt[3], smtpt[3];
19463 REAL maxminvol = 0.0, minvol = 0.0, ori;
19464 int success, maxidx = 0;
19468 pc = apex(abtets[0]);
19469 pd = oppo(abtets[n-1]);
19476 for (i = 0; i < n; i++) {
19477 edestoppo(abtets[i], worktet);
19478 cavetetlist->newindex((
void **) &parytet);
19479 *parytet = worktet;
19480 eorgoppo(abtets[i], worktet);
19481 cavetetlist->newindex((
void **) &parytet);
19482 *parytet = worktet;
19489 for (i = 0; i < 3; i++) vcd[i] = pd[i] - pc[i];
19492 for (it = 1; it < N; it++) {
19493 for (i = 0; i < 3; i++) {
19494 sampt[i] = pc[i] + (stepi * (double) it) * vcd[i];
19496 for (i = 0; i < cavetetlist->objects; i++) {
19497 parytet = (triface *) fastlookup(cavetetlist, i);
19498 ori = orient3d(dest(*parytet), org(*parytet), apex(*parytet), sampt);
19502 if (minvol > ori) minvol = ori;
19506 maxminvol = minvol;
19509 if (maxminvol < minvol) {
19510 maxminvol = minvol;
19516 if (maxminvol <= 0) {
19517 cavetetlist->restart();
19521 for (i = 0; i < 3; i++) {
19522 smtpt[i] = pc[i] + (stepi * (double) maxidx) * vcd[i];
19527 maketetrahedron(&faketet1);
19528 setvertices(faketet1, pd, pc, org(abtets[0]), dummypoint);
19529 cavetetlist->newindex((
void **) &parytet);
19530 *parytet = faketet1;
19531 maketetrahedron(&faketet2);
19532 setvertices(faketet2, pc, pd, dest(abtets[0]), dummypoint);
19533 cavetetlist->newindex((
void **) &parytet);
19534 *parytet = faketet2;
19537 opm.max_min_volume = 1;
19538 opm.numofsearchdirs = 20;
19539 opm.searchstep = 0.001;
19544 success = smoothpoint(smtpt, cavetetlist, 1, &opm);
19547 while (opm.smthiter == 100) {
19550 opm.searchstep *= 10.0;
19552 opm.initval = opm.imprval;
19554 smoothpoint(smtpt, cavetetlist, 1, &opm);
19559 tetrahedrondealloc(faketet1.tet);
19560 tetrahedrondealloc(faketet2.tet);
19562 cavetetlist->restart();
19570 makepoint(&steinerpt, FREEVOLVERTEX);
19571 for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i];
19574 for (i = 0; i < n; i++) {
19576 caveoldtetlist->newindex((
void **) &parytet);
19577 *parytet = abtets[i];
19579 worktet = abtets[0];
19580 ivf.iloc = (int) INSTAR;
19581 ivf.chkencflag = chkencflag;
19582 ivf.assignmeshsize = b->metric;
19583 if (ivf.assignmeshsize) {
19585 locate(steinerpt, &(abtets[0]));
19586 worktet = abtets[0];
19591 if (insertpoint(steinerpt, &worktet, NULL, NULL, &ivf)) {
19594 if (steinerleft > 0) steinerleft--;
19598 pointdealloc(steinerpt);
19609 int tetgenmesh::add_steinerpt_in_segment(face* misseg,
int searchlevel)
19612 face *paryseg, candseg;
19613 point startpt, endpt, pc, pd;
19614 flipconstraints fc;
19615 enum interresult dir;
19616 REAL P[3], Q[3], tp, tq;
19617 REAL len, smlen = 0, split = 0, split_q = 0;
19618 #pragma GCC diagnostic push 19619 #pragma GCC diagnostic ignored "-Wunused-but-set-variable" 19621 #pragma GCC diagnostic pop 19624 startpt = sorg(*misseg);
19625 endpt = sdest(*misseg);
19627 fc.seg[0] = startpt;
19629 fc.checkflipeligibility = 1;
19630 fc.collectencsegflag = 1;
19632 point2tetorg(startpt, searchtet);
19633 dir = finddirection(&searchtet, endpt);
19635 enextesymself(searchtet);
19637 int bak_fliplinklevel = b->fliplinklevel;
19638 b->fliplinklevel = searchlevel;
19640 if (dir == ACROSSFACE) {
19642 success = removefacebyflips(&searchtet, &fc);
19643 }
else if (dir == ACROSSEDGE) {
19645 success = removeedgebyflips(&searchtet, &fc);
19649 for (i = 0; i < caveencseglist->objects; i++) {
19650 paryseg = (face *) fastlookup(caveencseglist, i);
19651 suninfect(*paryseg);
19653 pc = sorg(*paryseg);
19654 pd = sdest(*paryseg);
19656 if (linelineint(startpt, endpt, pc, pd, P, Q, &tp, &tq)) {
19659 if ((tp > 0) && (tq < 1)) {
19661 if (tp < (b->epsilon * 1e+3)) tp = 0.0;
19663 if ((1.0 - tp) < (b->epsilon * 1e+3)) tp = 1.0;
19666 if ((tp <= 0) || (tp >= 1))
continue;
19667 if ((tq > 0) && (tq < 1)) {
19669 if (tq < (b->epsilon * 1e+3)) tq = 0.0;
19671 if ((1.0 - tq) < (b->epsilon * 1e+3)) tq = 1.0;
19674 if ((tq <= 0) || (tq >= 1))
continue;
19676 len = distance(P, Q);
19681 candseg = *paryseg;
19687 candseg = *paryseg;
19693 caveencseglist->restart();
19694 b->fliplinklevel = bak_fliplinklevel;
19703 point steinerpt, *parypt;
19704 insertvertexflags ivf;
19706 if (b->addsteiner_algo == 1) {
19708 makepoint(&steinerpt, FREESEGVERTEX);
19709 for (i = 0; i < 3; i++) {
19710 steinerpt[i] = startpt[i] + split * (endpt[i] - startpt[i]);
19713 for (i = 0; i < 3; i++) {
19714 P[i] = startpt[i] + split * (endpt[i] - startpt[i]);
19716 pc = sorg(candseg);
19717 pd = sdest(candseg);
19718 for (i = 0; i < 3; i++) {
19719 Q[i] = pc[i] + split_q * (pd[i] - pc[i]);
19721 makepoint(&steinerpt, FREEVOLVERTEX);
19722 for (i = 0; i < 3; i++) {
19723 steinerpt[i] = 0.5 * (P[i] + Q[i]);
19729 point2tetorg(startpt, searchtet);
19731 point2tetorg(endpt, searchtet);
19733 if (b->addsteiner_algo == 1) {
19734 splitseg = *misseg;
19735 spivot(*misseg, splitsh);
19738 splitseg.sh = NULL;
19740 ivf.iloc = (int) OUTSIDE;
19744 ivf.chkencflag = 0;
19745 ivf.sloc = (int) ONEDGE;
19747 ivf.splitbdflag = 0;
19749 ivf.respectbdflag = 1;
19750 ivf.assignmeshsize = b->metric;
19752 if (!insertpoint(steinerpt, &searchtet, &splitsh, &splitseg, &ivf)) {
19753 pointdealloc(steinerpt);
19757 if (b->addsteiner_algo == 1) {
19760 subvertstack->newindex((
void **) &parypt);
19761 *parypt = steinerpt;
19765 subsegstack->newindex((
void **) &paryseg);
19766 *paryseg = *misseg;
19769 if (steinerleft > 0) steinerleft--;
19780 int tetgenmesh::addsteiner4recoversegment(face* misseg,
int splitsegflag)
19782 triface *abtets, searchtet, spintet;
19785 point startpt, endpt;
19786 point pa, pb, pd, steinerpt, *parypt;
19787 enum interresult dir;
19788 insertvertexflags ivf;
19789 int types[2], poss[4];
19790 int n, endi, success;
19794 startpt = sorg(*misseg);
19795 if (pointtype(startpt) == FREESEGVERTEX) {
19796 sesymself(*misseg);
19797 startpt = sorg(*misseg);
19799 endpt = sdest(*misseg);
19802 point2tetorg(startpt, searchtet);
19803 dir = finddirection(&searchtet, endpt);
19804 enextself(searchtet);
19806 if (dir == ACROSSFACE) {
19809 esymself(searchtet);
19810 fsym(searchtet, spintet);
19811 pd = oppo(spintet);
19812 for (i = 0; i < 3; i++) {
19814 pb = dest(spintet);
19815 if (tri_edge_test(pa, pb, pd, startpt, endpt, NULL, 1, types, poss)) {
19818 enextself(spintet);
19819 eprevself(searchtet);
19821 esymself(searchtet);
19824 spintet = searchtet;
19828 if (apex(spintet) == endpt) {
19832 fnextself(spintet);
19833 if (spintet.tet == searchtet.tet)
break;
19839 abtets =
new triface[n];
19840 spintet = searchtet;
19841 for (i = 0; i < n; i++) {
19842 abtets[i] = spintet;
19843 fnextself(spintet);
19848 if (dir == ACROSSFACE) {
19850 if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) {
19853 }
else if (dir == ACROSSEDGE) {
19855 if (issubseg(searchtet)) {
19856 terminatetetgen(
this, 2);
19866 if (add_steinerpt_in_schoenhardtpoly(abtets, endi, 0)) {
19870 if ((n - endi) > 2) {
19872 if (add_steinerpt_in_schoenhardtpoly(&(abtets[endi]), n - endi, 0)) {
19881 terminatetetgen(
this, 2);
19884 terminatetetgen(
this, 2);
19891 subsegstack->newindex((
void **) &paryseg);
19892 *paryseg = *misseg;
19897 if (!splitsegflag) {
19901 if (b->verbose > 2) {
19902 printf(
" Splitting segment (%d, %d)\n", pointmark(startpt),
19907 if (b->addsteiner_algo > 0) {
19908 if (add_steinerpt_in_segment(misseg, 3)) {
19911 sesymself(*misseg);
19912 if (add_steinerpt_in_segment(misseg, 3)) {
19915 sesymself(*misseg);
19921 if (steinerpt == NULL) {
19923 makepoint(&steinerpt, FREESEGVERTEX);
19924 for (i = 0; i < 3; i++) {
19925 steinerpt[i] = 0.5 * (startpt[i] + endpt[i]);
19929 spivot(*misseg, splitsh);
19930 ivf.iloc = (int) OUTSIDE;
19934 ivf.chkencflag = 0;
19935 ivf.sloc = (int) ONEDGE;
19937 ivf.splitbdflag = 0;
19939 ivf.respectbdflag = 1;
19940 ivf.assignmeshsize = b->metric;
19941 if (!insertpoint(steinerpt, &searchtet, &splitsh, misseg, &ivf)) {
19942 terminatetetgen(
this, 2);
19948 subvertstack->newindex((
void **) &parypt);
19949 *parypt = steinerpt;
19952 if (steinerleft > 0) steinerleft--;
19969 int tetgenmesh::recoversegments(arraypool *misseglist,
int fullsearch,
19972 triface searchtet, spintet;
19973 face sseg, *paryseg;
19974 point startpt, endpt;
19978 long bak_inpoly_count = st_volref_count;
19979 long bak_segref_count = st_segref_count;
19981 if (b->verbose > 1) {
19982 printf(
" Recover segments [%s level = %2d] #: %ld.\n",
19983 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
19984 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
19985 subsegstack->objects);
19989 while (subsegstack->objects > 0l) {
19991 subsegstack->objects--;
19992 paryseg = (face *) fastlookup(subsegstack, subsegstack->objects);
19996 sstpivot1(sseg, searchtet);
19997 if (searchtet.tet != NULL) {
20001 startpt = sorg(sseg);
20002 endpt = sdest(sseg);
20004 if (b->verbose > 2) {
20005 printf(
" Recover segment (%d, %d).\n", pointmark(startpt),
20011 if (recoveredgebyflips(startpt, endpt, &sseg, &searchtet, 0)) {
20015 if (recoveredgebyflips(endpt, startpt, &sseg, &searchtet, 0)) {
20020 if (!success && fullsearch) {
20021 if (recoveredgebyflips(startpt, endpt, &sseg, &searchtet, fullsearch)) {
20029 sstbond1(sseg, searchtet);
20031 spintet = searchtet;
20033 tssbond1(spintet, sseg);
20034 fnextself(spintet);
20035 }
while (spintet.tet != searchtet.tet);
20037 if (steinerflag > 0) {
20039 if (addsteiner4recoversegment(&sseg, 0)) {
20042 if (!success && (steinerflag > 1)) {
20044 addsteiner4recoversegment(&sseg, 1);
20049 if (misseglist != NULL) {
20051 misseglist->newindex((
void **) &paryseg);
20060 if (b->verbose > 1) {
20062 if (st_volref_count > bak_inpoly_count) {
20063 printf(
" Add %ld Steiner points in volume.\n",
20064 st_volref_count - bak_inpoly_count);
20066 if (st_segref_count > bak_segref_count) {
20067 printf(
" Add %ld Steiner points in segments.\n",
20068 st_segref_count - bak_segref_count);
20093 int tetgenmesh::recoverfacebyflips(point pa, point pb, point pc,
20094 face *searchsh, triface* searchtet)
20096 triface spintet, flipedge;
20098 flipconstraints fc;
20099 int types[2], poss[4], intflag;
20108 fc.checkflipeligibility = 1;
20111 for (i = 0; i < 3 && !success; i++) {
20114 point2tetorg(fc.fac[i], *searchtet);
20115 finddirection(searchtet, fc.fac[(i+1)%3]);
20117 spintet = *searchtet;
20119 if (apex(spintet) == fc.fac[(i+2)%3]) {
20121 *searchtet = spintet;
20123 for (j = i; j > 0; j--) {
20124 eprevself(*searchtet);
20129 fnextself(spintet);
20130 if (spintet.tet == searchtet->tet)
break;
20132 if (success)
break;
20134 flipedge.tet = NULL;
20136 spintet = *searchtet;
20138 pd = apex(spintet);
20139 pe = oppo(spintet);
20140 if ((pd != dummypoint) && (pe != dummypoint)) {
20142 intflag = tri_edge_test(pa, pb, pc, pd, pe, NULL, 1, types, poss);
20146 if (intflag == 2) {
20148 edestoppo(spintet, flipedge);
20149 if (searchsh != NULL) {
20151 if ((types[0] == (
int) ACROSSFACE) ||
20152 (types[0] == (
int) ACROSSEDGE)) {
20154 if (issubseg(flipedge)) {
20155 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20156 intflag, types, poss);
20159 triface chkface = flipedge;
20161 if (issubface(chkface))
break;
20163 if (chkface.tet == flipedge.tet)
break;
20165 if (issubface(chkface)) {
20167 return report_selfint_face(pa, pb, pc,searchsh,&chkface,
20168 intflag, types, poss);
20171 }
else if (types[0] == TOUCHFACE) {
20173 point touchpt, *parypt;
20174 if (poss[1] == 0) {
20179 if (pointtype(touchpt) == FREEVOLVERTEX) {
20182 face checksh, *parysh;
20183 int siloc = (int) ONFACE;
20185 setpointtype(touchpt, FREEFACETVERTEX);
20186 sinsertvertex(touchpt, searchsh, NULL, siloc, sbowat, 0);
20190 subvertstack->newindex((
void **) &parypt);
20194 for (i = 0; i < caveshbdlist->objects; i++) {
20196 parysh = (face *) fastlookup(caveshbdlist, i);
20197 spivot(*parysh, checksh);
20199 if (checksh.sh[3] != NULL) {
20200 subfacstack->newindex((
void **) &parysh);
20205 for (i = 0; i < caveshlist->objects; i++) {
20206 parysh = (face *) fastlookup(caveshlist, i);
20207 shellfacedealloc(subfaces, parysh->sh);
20210 caveshlist->restart();
20211 caveshbdlist->restart();
20212 cavesegshlist->restart();
20214 searchsh->sh = NULL;
20218 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20219 intflag, types, poss);
20224 return report_selfint_face(pa, pb, pc, searchsh, &flipedge,
20225 intflag, types, poss);
20229 terminatetetgen(
this, 2);
20234 fnextself(spintet);
20235 if (spintet.tet == searchtet->tet) {
20236 terminatetetgen(
this, 2);
20240 if (removeedgebyflips(&flipedge, &fc) == 2) {
20257 int tetgenmesh::recoversubfaces(arraypool *misshlist,
int steinerflag)
20259 triface searchtet, neightet, spintet;
20260 face searchsh, neighsh, neineish, *parysh;
20262 point startpt, endpt, apexpt, *parypt;
20264 insertvertexflags ivf;
20269 if (b->verbose > 1) {
20270 printf(
" Recover subfaces [%s level = %2d] #: %ld.\n",
20271 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
20272 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
20273 subfacstack->objects);
20277 while (subfacstack->objects > 0l) {
20279 subfacstack->objects--;
20280 parysh = (face *) fastlookup(subfacstack, subfacstack->objects);
20281 searchsh = *parysh;
20283 if (searchsh.sh[3] == NULL)
continue;
20285 stpivot(searchsh, neightet);
20286 if (neightet.tet != NULL)
continue;
20289 if (b->verbose > 2) {
20290 printf(
" Recover subface (%d, %d, %d).\n",pointmark(sorg(searchsh)),
20291 pointmark(sdest(searchsh)), pointmark(sapex(searchsh)));
20295 for (i = 0; i < 3; i++) {
20296 sspivot(searchsh, bdsegs[i]);
20297 if (bdsegs[i].sh != NULL) {
20299 sstpivot1(bdsegs[i], searchtet);
20300 if (searchtet.tet == NULL) {
20301 terminatetetgen(
this, 2);
20307 startpt = sorg(searchsh);
20308 endpt = sdest(searchsh);
20309 point2tetorg(startpt, searchtet);
20310 finddirection(&searchtet, endpt);
20311 if (dest(searchtet) == endpt) {
20315 if (recoveredgebyflips(startpt, endpt, &searchsh, &searchtet, 0)) {
20318 if (recoveredgebyflips(endpt, startpt, &searchsh, &searchtet, 0)) {
20325 makeshellface(subsegs, &(bdsegs[i]));
20326 setshvertices(bdsegs[i], startpt, endpt, NULL);
20327 smarktest2(bdsegs[i]);
20329 ssbond(searchsh, bdsegs[i]);
20330 spivot(searchsh, neighsh);
20331 if (neighsh.sh != NULL) {
20332 ssbond(neighsh, bdsegs[i]);
20335 sstbond1(bdsegs[i], searchtet);
20337 spintet = searchtet;
20339 tssbond1(spintet, bdsegs[i]);
20340 fnextself(spintet);
20341 }
while (spintet.tet != searchtet.tet);
20345 for (j = (i - 1); j >= 0; j--) {
20346 if (smarktest2ed(bdsegs[j])) {
20347 spivot(bdsegs[j], neineish);
20348 ssdissolve(neineish);
20349 spivot(neineish, neighsh);
20350 if (neighsh.sh != NULL) {
20351 ssdissolve(neighsh);
20353 sstpivot1(bdsegs[j], searchtet);
20354 spintet = searchtet;
20356 tssdissolve1(spintet);
20357 fnextself(spintet);
20358 if (spintet.tet == searchtet.tet)
break;
20360 shellfacedealloc(subsegs, bdsegs[j].sh);
20365 if (b->verbose > 2) {
20366 printf(
" Add a Steiner point in subedge (%d, %d).\n",
20367 pointmark(startpt), pointmark(endpt));
20369 makepoint(&steinerpt, FREEFACETVERTEX);
20370 for (j = 0; j < 3; j++) {
20371 steinerpt[j] = 0.5 * (startpt[j] + endpt[j]);
20374 point2tetorg(startpt, searchtet);
20375 ivf.iloc = (int) OUTSIDE;
20379 ivf.chkencflag = 0;
20380 ivf.sloc = (int) ONEDGE;
20382 ivf.splitbdflag = 0;
20384 ivf.respectbdflag = 1;
20385 ivf.assignmeshsize = b->metric;
20386 if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) {
20387 terminatetetgen(
this, 2);
20391 subvertstack->newindex((
void **) &parypt);
20392 *parypt = steinerpt;
20395 if (steinerleft > 0) steinerleft--;
20400 senextself(searchsh);
20405 startpt = sorg(searchsh);
20406 endpt = sdest(searchsh);
20407 apexpt = sapex(searchsh);
20409 success = recoverfacebyflips(startpt,endpt,apexpt,&searchsh,&searchtet);
20412 for (j = 0; j < 3; j++) {
20413 if (smarktest2ed(bdsegs[j])) {
20414 spivot(bdsegs[j], neineish);
20415 ssdissolve(neineish);
20416 spivot(neineish, neighsh);
20417 if (neighsh.sh != NULL) {
20418 ssdissolve(neighsh);
20420 sstpivot1(bdsegs[j], neightet);
20421 spintet = neightet;
20423 tssdissolve1(spintet);
20424 fnextself(spintet);
20425 if (spintet.tet == neightet.tet)
break;
20427 shellfacedealloc(subsegs, bdsegs[j].sh);
20432 if (searchsh.sh != NULL) {
20434 tsbond(searchtet, searchsh);
20435 fsymself(searchtet);
20436 sesymself(searchsh);
20437 tsbond(searchtet, searchsh);
20442 if (b->verbose > 2) {
20443 printf(
" Add a Steiner point in subface (%d, %d, %d).\n",
20444 pointmark(startpt), pointmark(endpt), pointmark(apexpt));
20446 makepoint(&steinerpt, FREEFACETVERTEX);
20447 for (j = 0; j < 3; j++) {
20448 steinerpt[j] = (startpt[j] + endpt[j] + apexpt[j]) / 3.0;
20451 point2tetorg(startpt, searchtet);
20452 ivf.iloc = (int) OUTSIDE;
20456 ivf.chkencflag = 0;
20457 ivf.sloc = (int) ONFACE;
20459 ivf.splitbdflag = 0;
20461 ivf.respectbdflag = 1;
20462 ivf.assignmeshsize = b->metric;
20463 if (!insertpoint(steinerpt, &searchtet, &searchsh, NULL, &ivf)) {
20464 terminatetetgen(
this, 2);
20468 subvertstack->newindex((
void **) &parypt);
20469 *parypt = steinerpt;
20472 if (steinerleft > 0) steinerleft--;
20480 if (misshlist != NULL) {
20482 misshlist->newindex((
void **) &parysh);
20483 *parysh = searchsh;
20509 int tetgenmesh::getvertexstar(
int fullstar, point searchpt, arraypool* tetlist,
20510 arraypool* vertlist, arraypool* shlist)
20512 triface searchtet, neightet, *parytet;
20513 face checksh, *parysh;
20519 point2tetorg(searchpt, searchtet);
20522 enextesymself(searchtet);
20525 tetlist->newindex((
void **) &parytet);
20526 *parytet = searchtet;
20527 if (vertlist != NULL) {
20529 j = (searchtet.ver & 3);
20530 for (i = 1; i < 4; i++) {
20531 pt = (point) searchtet.tet[4 + ((j + i) % 4)];
20533 vertlist->newindex((
void **) &parypt);
20539 esym(searchtet, neightet);
20540 if (issubface(neightet)) {
20541 if (shlist != NULL) {
20542 tspivot(neightet, checksh);
20543 if (!sinfected(checksh)) {
20545 sinfected(checksh);
20546 shlist->newindex((
void **) &parysh);
20555 fsymself(neightet);
20556 esymself(neightet);
20559 tetlist->newindex((
void **) &parytet);
20560 *parytet = neightet;
20561 if (vertlist != NULL) {
20563 pt = apex(neightet);
20565 vertlist->newindex((
void **) &parypt);
20571 for (i = 0; i < tetlist->objects; i++) {
20572 searchtet = * (triface *) fastlookup(tetlist, i);
20576 for (j = 0; j < 2; j++) {
20578 enextself(searchtet);
20579 esym(searchtet, neightet);
20580 if (issubface(neightet)) {
20581 if (shlist != NULL) {
20582 tspivot(neightet, checksh);
20583 if (!sinfected(checksh)) {
20585 sinfected(checksh);
20586 shlist->newindex((
void **) &parysh);
20595 fsymself(neightet);
20596 if (!infected(neightet)) {
20597 esymself(neightet);
20599 tetlist->newindex((
void **) &parytet);
20600 *parytet = neightet;
20601 if (vertlist != NULL) {
20603 pt = apex(neightet);
20604 if (!pinfected(pt)) {
20606 vertlist->newindex((
void **) &parypt);
20617 for (i = 0; i < tetlist->objects; i++) {
20618 parytet = (triface *) fastlookup(tetlist, i);
20619 uninfect(*parytet);
20622 if (vertlist != NULL) {
20623 for (i = 0; i < vertlist->objects; i++) {
20624 parypt = (point *) fastlookup(vertlist, i);
20625 puninfect(*parypt);
20629 if (shlist != NULL) {
20630 for (i = 0; i < shlist->objects; i++) {
20631 parysh = (face *) fastlookup(shlist, i);
20632 suninfect(*parysh);
20636 return (
int) tetlist->objects;
20651 int tetgenmesh::getedge(point e1, point e2, triface *tedge)
20653 triface searchtet, neightet, *parytet;
20658 if (b->verbose > 2) {
20659 printf(
" Get edge from %d to %d.\n", pointmark(e1), pointmark(e2));
20663 if (!isdeadtet(*tedge)) {
20664 if (org(*tedge) == e1) {
20665 if (dest(*tedge) == e2) {
20668 }
else if (org(*tedge) == e2) {
20669 if (dest(*tedge) == e1) {
20677 point2tetorg(e1, *tedge);
20678 finddirection(tedge, e2);
20679 if (dest(*tedge) == e2) {
20683 point2tetorg(e2, *tedge);
20684 finddirection(tedge, e1);
20685 if (dest(*tedge) == e1) {
20693 point2tetorg(e1, searchtet);
20694 enextesymself(searchtet);
20695 arraypool *tetlist = cavebdrylist;
20698 for (i = 0; i < 3; i++) {
20699 pt = apex(searchtet);
20702 eorgoppo(searchtet, *tedge);
20705 enextself(searchtet);
20709 fnext(searchtet, neightet);
20710 esymself(neightet);
20712 pt = apex(neightet);
20715 eorgoppo(neightet, *tedge);
20721 tetlist->newindex((
void **) &parytet);
20722 *parytet = searchtet;
20724 tetlist->newindex((
void **) &parytet);
20725 *parytet = neightet;
20729 for (i = 0; (i < tetlist->objects) && !done; i++) {
20730 parytet = (triface *) fastlookup(tetlist, i);
20731 searchtet = *parytet;
20732 for (j = 0; (j < 2) && !done; j++) {
20733 enextself(searchtet);
20734 fnext(searchtet, neightet);
20735 if (!infected(neightet)) {
20736 esymself(neightet);
20737 pt = apex(neightet);
20740 eorgoppo(neightet, *tedge);
20744 tetlist->newindex((
void **) &parytet);
20745 *parytet = neightet;
20752 for (i = 0; i < tetlist->objects; i++) {
20753 parytet = (triface *) fastlookup(tetlist, i);
20754 uninfect(*parytet);
20756 tetlist->restart();
20769 int tetgenmesh::reduceedgesatvertex(point startpt, arraypool* endptlist)
20772 point *pendpt, *parypt;
20773 enum interresult dir;
20774 flipconstraints fc;
20780 fc.remvert = startpt;
20781 fc.checkflipeligibility = 1;
20787 for (i = 0; i < endptlist->objects; i++) {
20788 pendpt = (point *) fastlookup(endptlist, i);
20789 if (*pendpt == dummypoint) {
20795 if (getedge(startpt, *pendpt, &searchtet)) {
20802 point2tetorg(startpt, searchtet);
20803 dir = finddirection(&searchtet, *pendpt);
20805 if (dir == ACROSSVERT) {
20806 if (dest(searchtet) == *pendpt) {
20808 if (!issubseg(searchtet)) {
20809 n = removeedgebyflips(&searchtet, &fc);
20822 j = endptlist->objects - 1;
20823 parypt = (point *) fastlookup(endptlist, j);
20825 endptlist->objects--;
20837 return (
int) endptlist->objects;
20856 int tetgenmesh::removevertexbyflips(point steinerpt)
20858 triface *fliptets = NULL, wrktets[4];
20859 triface searchtet, spintet, neightet;
20860 face parentsh, spinsh, checksh;
20861 face leftseg, rightseg, checkseg;
20862 point lpt = NULL, rpt = NULL, apexpt;
20863 flipconstraints fc;
20865 enum locateresult loc;
20866 int valence, removeflag;
20871 vt = pointtype(steinerpt);
20874 if (vt == FREESEGVERTEX) {
20875 sdecode(point2sh(steinerpt), leftseg);
20877 if (sdest(leftseg) == steinerpt) {
20878 senext(leftseg, rightseg);
20879 spivotself(rightseg);
20880 rightseg.shver = 0;
20882 rightseg = leftseg;
20883 senext2(rightseg, leftseg);
20884 spivotself(leftseg);
20887 lpt = sorg(leftseg);
20888 rpt = sdest(rightseg);
20889 if (b->verbose > 2) {
20890 printf(
" Removing Steiner point %d in segment (%d, %d).\n",
20891 pointmark(steinerpt), pointmark(lpt), pointmark(rpt));
20894 }
else if (vt == FREEFACETVERTEX) {
20895 if (b->verbose > 2) {
20896 printf(
" Removing Steiner point %d in facet.\n",
20897 pointmark(steinerpt));
20899 }
else if (vt == FREEVOLVERTEX) {
20900 if (b->verbose > 2) {
20901 printf(
" Removing Steiner point %d in volume.\n",
20902 pointmark(steinerpt));
20904 }
else if (vt == VOLVERTEX) {
20905 if (b->verbose > 2) {
20906 printf(
" Removing a point %d in volume.\n",
20907 pointmark(steinerpt));
20915 getvertexstar(1, steinerpt, cavetetlist, cavetetvertlist, NULL);
20916 cavetetlist->restart();
20917 if (cavetetvertlist->objects > 3l) {
20918 valence = reduceedgesatvertex(steinerpt, cavetetvertlist);
20920 valence = cavetetvertlist->objects;
20922 cavetetvertlist->restart();
20926 if (valence == 4) {
20929 point2tetorg(steinerpt, searchtet);
20930 loc = INTETRAHEDRON;
20932 }
else if (valence == 5) {
20934 if (vt == FREESEGVERTEX) {
20935 sstpivot1(leftseg, searchtet);
20936 if (org(searchtet) != steinerpt) {
20937 esymself(searchtet);
20940 neightet.tet = NULL;
20941 spintet = searchtet;
20944 if (apex(spintet) == rpt) {
20946 neightet = spintet;
20948 fnextself(spintet);
20949 if (spintet.tet == searchtet.tet)
break;
20953 }
else if (i == 4) {
20956 if (apex(neightet) == rpt) {
20960 esym(neightet, searchtet);
20961 enextself(searchtet);
20963 wrktets[0] = searchtet;
20964 for (i = 0; i < 2; i++) {
20965 fnext(wrktets[i], wrktets[i+1]);
20967 if (apex(wrktets[0]) == oppo(wrktets[2])) {
20973 }
else if (vt == FREEFACETVERTEX) {
20975 point2tetorg(steinerpt, searchtet);
20978 wrktets[0] = searchtet;
20979 wrktets[1] = searchtet;
20980 esymself(wrktets[1]);
20981 enextself(wrktets[1]);
20982 wrktets[2] = searchtet;
20983 eprevself(wrktets[2]);
20984 esymself(wrktets[2]);
20987 searchtet.tet = NULL;
20988 for (i = 0; i < 3; i++) {
20989 spintet = wrktets[i];
20993 fnextself(spintet);
20994 if (spintet.tet == wrktets[i].tet)
break;
20996 if (valence == 3) {
20998 searchtet = wrktets[i];
21011 if (vt == FREESEGVERTEX) {
21015 sstpivot1(leftseg, searchtet);
21016 if (org(searchtet) != steinerpt) {
21017 esymself(searchtet);
21019 spintet = searchtet;
21022 eprev(spintet, neightet);
21023 esymself(neightet);
21025 fsymself(neightet);
21026 if (oppo(neightet) != rpt) {
21032 point chkp1 = org(neightet);
21033 point chkp2 = apex(neightet);
21034 REAL chkori = orient3d(rpt, lpt, chkp1, chkp2);
21035 if (chkori >= 0.0) {
21040 fnextself(spintet);
21041 if (spintet.tet == searchtet.tet) {
21052 if (vt == FREESEGVERTEX) {
21054 if (getedge(lpt, rpt, &searchtet)) {
21057 if (!checksubfaceflag) {
21062 for (i = 0; i < 2; i++) {
21063 checkseg = (i == 0) ? leftseg : rightseg;
21064 sstpivot1(checkseg, neightet);
21065 spintet = neightet;
21067 tssdissolve1(spintet);
21068 fnextself(spintet);
21069 if (spintet.tet == neightet.tet)
break;
21071 sstdissolve1(checkseg);
21074 spivot(rightseg, parentsh);
21075 sremovevertex(steinerpt, &parentsh, &rightseg, slawson);
21077 caveshbdlist->restart();
21079 sstbond1(rightseg, searchtet);
21080 spintet = searchtet;
21082 tssbond1(spintet, rightseg);
21083 fnextself(spintet);
21084 if (spintet.tet == searchtet.tet)
break;
21087 setpointtype(steinerpt, FREEVOLVERTEX);
21100 if (vt == FREESEGVERTEX) {
21102 for (i = 0; i < 2; i++) {
21103 checkseg = (i == 0) ? leftseg : rightseg;
21104 sstpivot1(checkseg, neightet);
21105 spintet = neightet;
21107 tssdissolve1(spintet);
21108 fnextself(spintet);
21109 if (spintet.tet == neightet.tet)
break;
21111 sstdissolve1(checkseg);
21113 if (checksubfaceflag) {
21115 for (i = 0; i < 2; i++) {
21116 checkseg = (i == 0) ? leftseg : rightseg;
21117 spivot(checkseg, parentsh);
21118 if (parentsh.sh != NULL) {
21121 stpivot(spinsh, neightet);
21122 if (neightet.tet != NULL) {
21123 tsdissolve(neightet);
21126 stpivot(spinsh, neightet);
21127 if (neightet.tet != NULL) {
21128 tsdissolve(neightet);
21130 stdissolve(spinsh);
21131 spivotself(spinsh);
21132 if (spinsh.sh == parentsh.sh)
break;
21139 if (loc == INTETRAHEDRON) {
21141 fliptets =
new triface[4];
21142 fliptets[0] = searchtet;
21143 for (i = 0; i < 2; i++) {
21144 fnext(fliptets[i], fliptets[i+1]);
21146 eprev(fliptets[0], fliptets[3]);
21147 fnextself(fliptets[3]);
21148 eprevself(fliptets[3]);
21149 esymself(fliptets[3]);
21187 if (vt == FREEFACETVERTEX) {
21190 triface checktet, chkface;
21191 for (i = 0; i < 3; i++) {
21192 enext(fliptets[i], checktet);
21193 esymself(checktet);
21194 int scount = 0;
int k;
21195 for (k = 0; k < 3; k++) {
21196 esym(checktet, chkface);
21197 if (issubface(chkface)) scount++;
21198 enextself(checktet);
21202 }
else if (scount == 2) {
21205 delete [] fliptets;
21212 for (i = 0; i < 3; i++) {
21213 eprev(fliptets[i], checktet);
21214 esymself(checktet);
21215 if (issubface(chkface)) scount++;
21219 delete [] fliptets;
21224 flip41(fliptets, 1, &fc);
21226 }
else if (loc == ONFACE) {
21230 fliptets =
new triface[6];
21231 fliptets[0] = searchtet;
21232 for (i = 0; i < 2; i++) {
21233 fnext(fliptets[i], fliptets[i+1]);
21235 eprev(fliptets[0], fliptets[3]);
21236 fnextself(fliptets[3]);
21237 esymself(fliptets[3]);
21238 eprevself(fliptets[3]);
21239 for (i = 3; i < 5; i++) {
21240 fnext(fliptets[i], fliptets[i+1]);
21242 if (vt == FREEFACETVERTEX) {
21245 for (i = 3; i < 6; i++) {
21246 if (issubface(fliptets[i])) valence++;
21251 for (i = 0; i < 3; i++) {
21252 esym(fliptets[i+3], wrktets[i]);
21253 esym(fliptets[i], fliptets[i+3]);
21254 fliptets[i] = wrktets[i];
21257 wrktets[1] = fliptets[1];
21258 fliptets[1] = fliptets[2];
21259 fliptets[2] = wrktets[1];
21260 wrktets[1] = fliptets[4];
21261 fliptets[4] = fliptets[5];
21262 fliptets[5] = wrktets[1];
21266 triface checktet, chkface;
21267 for (i = 0; i < 3; i++) {
21268 enext(fliptets[i], checktet);
21269 esymself(checktet);
21270 int scount = 0;
int k;
21271 for (k = 0; k < 3; k++) {
21272 esym(checktet, chkface);
21273 if (issubface(chkface)) scount++;
21274 enextself(checktet);
21278 }
else if (scount == 2) {
21281 delete [] fliptets;
21288 for (i = 0; i < 3; i++) {
21289 eprev(fliptets[i], checktet);
21290 esymself(checktet);
21291 if (issubface(chkface)) scount++;
21295 delete [] fliptets;
21308 flip32(&(fliptets[3]), 1, &fc);
21312 flip41(fliptets, 1, &fc);
21314 }
else if (loc == ONEDGE) {
21320 spintet = searchtet;
21323 fnextself(spintet);
21324 if (spintet.tet == searchtet.tet)
break;
21327 fliptets =
new triface[2 * n];
21328 fliptets[0] = searchtet;
21329 for (i = 0; i < (n - 1); i++) {
21330 fnext(fliptets[i], fliptets[i+1]);
21332 eprev(fliptets[0], fliptets[n]);
21333 fnextself(fliptets[n]);
21334 esymself(fliptets[n]);
21335 eprevself(fliptets[n]);
21336 for (i = n; i < (2 * n - 1); i++) {
21337 fnext(fliptets[i], fliptets[i+1]);
21347 wrktets[0] = fliptets[0];
21348 eprevself(wrktets[0]);
21349 esymself(wrktets[0]);
21350 enextself(wrktets[0]);
21351 wrktets[1] = fliptets[n];
21352 enextself(wrktets[1]);
21353 esymself(wrktets[1]);
21354 eprevself(wrktets[1]);
21356 flip23(wrktets, 1, &fc);
21358 fliptets[n] = wrktets[2];
21360 fliptets[0] = wrktets[0];
21369 for (i = 1; i < (n - 1); i++) {
21370 wrktets[0] = wrktets[1];
21371 enextself(wrktets[0]);
21372 esymself(wrktets[0]);
21373 eprevself(wrktets[0]);
21374 wrktets[1] = fliptets[n+i];
21375 enextself(wrktets[1]);
21376 wrktets[2] = fliptets[i];
21377 eprevself(wrktets[2]);
21378 esymself(wrktets[2]);
21380 flip32(wrktets, 1, &fc);
21382 fliptets[i] = wrktets[0];
21383 esymself(fliptets[i]);
21393 wrktets[3] = wrktets[1];
21394 wrktets[0] = fliptets[n];
21395 eprevself(wrktets[0]);
21396 esymself(wrktets[0]);
21397 enextself(wrktets[0]);
21398 wrktets[1] = fliptets[n-1];
21399 esymself(wrktets[1]);
21400 enextself(wrktets[1]);
21401 wrktets[2] = fliptets[2*n-1];
21402 enextself(wrktets[2]);
21403 esymself(wrktets[2]);
21404 enextself(wrktets[2]);
21406 flip41(wrktets, 1, &fc);
21408 fliptets[n-1] = wrktets[0];
21412 delete [] fliptets;
21414 if (vt == FREESEGVERTEX) {
21419 slawson = (checksubfaceflag ? 0 : 1);
21420 spivot(rightseg, parentsh);
21421 sremovevertex(steinerpt, &parentsh, &rightseg, slawson);
21424 rightseg.shver = 0;
21426 point2tetorg(lpt, searchtet);
21427 finddirection(&searchtet, rpt);
21428 sstbond1(rightseg, searchtet);
21429 spintet = searchtet;
21431 tssbond1(spintet, rightseg);
21432 fnextself(spintet);
21433 if (spintet.tet == searchtet.tet)
break;
21436 if (checksubfaceflag) {
21438 spivot(rightseg, parentsh);
21439 if (parentsh.sh != NULL) {
21442 if (sorg(spinsh) != lpt) {
21445 apexpt = sapex(spinsh);
21447 spintet = searchtet;
21449 if (apex(spintet) == apexpt) {
21450 tsbond(spintet, spinsh);
21452 fsym(spintet, neightet);
21453 tsbond(neightet, spinsh);
21457 fnextself(spintet);
21459 spivotself(spinsh);
21460 if (spinsh.sh == parentsh.sh)
break;
21466 caveshbdlist->restart();
21470 if (pointtype(steinerpt) != UNUSEDVERTEX) {
21471 setpointtype(steinerpt, UNUSEDVERTEX);
21474 if (vt != VOLVERTEX) {
21476 if (vt == FREESEGVERTEX) {
21478 }
else if (vt == FREEFACETVERTEX) {
21480 }
else if (vt == FREEVOLVERTEX) {
21483 if (steinerleft > 0) steinerleft++;
21495 int tetgenmesh::suppressbdrysteinerpoint(point steinerpt)
21497 face parentsh, spinsh, *parysh;
21498 face leftseg, rightseg;
21499 point lpt = NULL, rpt = NULL;
21502 verttype vt = pointtype(steinerpt);
21504 if (vt == FREESEGVERTEX) {
21505 sdecode(point2sh(steinerpt), leftseg);
21507 if (sdest(leftseg) == steinerpt) {
21508 senext(leftseg, rightseg);
21509 spivotself(rightseg);
21510 rightseg.shver = 0;
21512 rightseg = leftseg;
21513 senext2(rightseg, leftseg);
21514 spivotself(leftseg);
21517 lpt = sorg(leftseg);
21518 rpt = sdest(rightseg);
21519 if (b->verbose > 2) {
21520 printf(
" Suppressing Steiner point %d in segment (%d, %d).\n",
21521 pointmark(steinerpt), pointmark(lpt), pointmark(rpt));
21524 spivot(leftseg, parentsh);
21525 if (parentsh.sh != NULL) {
21529 cavesegshlist->newindex((
void **) &parysh);
21532 if (sorg(*parysh)!= sorg(parentsh)) sesymself(*parysh);
21533 spivotself(spinsh);
21534 if (spinsh.sh == NULL)
break;
21535 if (spinsh.sh == parentsh.sh)
break;
21538 if (cavesegshlist->objects < 2) {
21540 cavesegshlist->restart();
21543 }
else if (vt == FREEFACETVERTEX) {
21544 if (b->verbose > 2) {
21545 printf(
" Suppressing Steiner point %d from facet.\n",
21546 pointmark(steinerpt));
21548 sdecode(point2sh(steinerpt), parentsh);
21550 for (i = 0; i < 2; i++) {
21551 cavesegshlist->newindex((
void **) &parysh);
21552 *parysh = parentsh;
21553 sesymself(parentsh);
21559 triface searchtet, neightet, *parytet;
21560 point pa, pb, pc, pd;
21561 REAL v1[3], v2[3], len, u;
21563 REAL startpt[3] = {0,}, samplept[3] = {0,}, candpt[3] = {0,};
21564 REAL ori, minvol, smallvol;
21568 int n = (int) cavesegshlist->objects;
21569 point *newsteiners =
new point[n];
21570 for (i = 0; i < n; i++) newsteiners[i] = NULL;
21573 for (i = 0; i < cavesegshlist->objects; i++) {
21574 parysh = (face *) fastlookup(cavesegshlist, i);
21575 stpivot(*parysh, searchtet);
21577 if (ishulltet(searchtet))
continue;
21581 setpoint2tet(steinerpt, encode(searchtet));
21582 getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist);
21584 pa = sorg(*parysh);
21585 pb = sdest(*parysh);
21586 pc = sapex(*parysh);
21587 facenormal(pa, pb, pc, v1, 1, NULL);
21588 len = sqrt(dot(v1, v1));
21592 if (vt == FREESEGVERTEX) {
21593 parysh = (face *) fastlookup(cavesegshlist, (i + 1) % n);
21594 pd = sapex(*parysh);
21595 facenormal(pb, pa, pd, v2, 1, NULL);
21596 len = sqrt(dot(v2, v2));
21601 v1[0] = 0.5 * (v1[0] + v2[0]);
21602 v1[1] = 0.5 * (v1[1] + v2[1]);
21603 v1[2] = 0.5 * (v1[2] + v2[2]);
21608 len = distance(pa, pb);
21609 v2[0] = steinerpt[0] + len * v1[0];
21610 v2[1] = steinerpt[1] + len * v1[1];
21611 v2[2] = steinerpt[2] + len * v1[2];
21612 for (j = 0; j < cavetetlist->objects; j++) {
21613 parytet = (triface *) fastlookup(cavetetlist, j);
21614 pa = org(*parytet);
21615 pb = dest(*parytet);
21616 pc = apex(*parytet);
21620 ori = orient3d(steinerpt, pa, pb, v2);
21622 ori = orient3d(steinerpt, pb, pc, v2);
21624 ori = orient3d(steinerpt, pc, pa, v2);
21627 planelineint(pa, pb, pc, steinerpt, v2, startpt, &u);
21633 if (j == cavetetlist->objects) {
21637 for (j = 0; j < caveshlist->objects; j++) {
21638 parysh = (face *) fastlookup(caveshlist, j);
21639 stpivot(*parysh, neightet);
21640 cavetetlist->newindex((
void **) &parytet);
21641 *parytet = neightet;
21646 v1[0] = steinerpt[0] - startpt[0];
21647 v1[1] = steinerpt[1] - startpt[1];
21648 v1[2] = steinerpt[2] - startpt[2];
21651 for (j = 1; j < samplesize - 1; j++) {
21652 samplept[0] = startpt[0] + ((REAL) j / (REAL) samplesize) * v1[0];
21653 samplept[1] = startpt[1] + ((REAL) j / (REAL) samplesize) * v1[1];
21654 samplept[2] = startpt[2] + ((REAL) j / (REAL) samplesize) * v1[2];
21657 for (k = 0; k < cavetetlist->objects; k++) {
21658 parytet = (triface *) fastlookup(cavetetlist, k);
21659 pa = org(*parytet);
21660 pb = dest(*parytet);
21661 pc = apex(*parytet);
21662 ori = orient3d(pb, pa, pc, samplept);
21665 REAL lab = distance(pa, pb);
21666 REAL lbc = distance(pb, pc);
21667 REAL lca = distance(pc, pa);
21668 REAL lv = (lab + lbc + lca) / 3.0;
21669 REAL l3 = lv*lv*lv;
21670 if (fabs(ori) / l3 < 1e-8) ori = 0.0;
21675 if (smallvol == -1) {
21678 if (ori < smallvol) smallvol = ori;
21681 if (k == cavetetlist->objects) {
21683 if (minvol == -1.0) {
21684 candpt[0] = samplept[0];
21685 candpt[1] = samplept[1];
21686 candpt[2] = samplept[2];
21689 if (minvol < smallvol) {
21691 candpt[0] = samplept[0];
21692 candpt[1] = samplept[1];
21693 candpt[2] = samplept[2];
21704 if (minvol > 0)
break;
21708 if (minvol == -1.0) {
21710 cavetetlist->restart();
21711 caveshlist->restart();
21715 makepoint(&(newsteiners[i]), FREEVOLVERTEX);
21716 newsteiners[i][0] = candpt[0];
21717 newsteiners[i][1] = candpt[1];
21718 newsteiners[i][2] = candpt[2];
21719 cavetetlist->restart();
21720 caveshlist->restart();
21723 if (i < cavesegshlist->objects) {
21725 for (; i > 0; i--) {
21726 if (newsteiners[i - 1] != NULL) {
21727 pointdealloc(newsteiners[i - 1]);
21730 delete [] newsteiners;
21731 cavesegshlist->restart();
21736 triface newtet, newface, spintet;
21737 face newsh, neighsh;
21738 face *splitseg, checkseg;
21742 if (vt == FREESEGVERTEX) {
21745 sstpivot1(leftseg, neightet);
21746 spintet = neightet;
21748 tssdissolve1(spintet);
21749 fnextself(spintet);
21750 if (spintet.tet == neightet.tet)
break;
21752 sstpivot1(rightseg, neightet);
21753 spintet = neightet;
21755 tssdissolve1(spintet);
21756 fnextself(spintet);
21757 if (spintet.tet == neightet.tet)
break;
21764 for (i = 0; i < cavesegshlist->objects; i++) {
21765 parysh = (face *) fastlookup(cavesegshlist, i);
21767 stpivot(*parysh, neightet);
21769 setpoint2tet(steinerpt, encode(neightet));
21770 getvertexstar(0, steinerpt, cavetetlist, NULL, caveshlist);
21771 if (!ishulltet(neightet)) {
21773 for (j = 0; j < cavetetlist->objects; j++) {
21774 parytet = (triface *) fastlookup(cavetetlist, j);
21775 setoppo(*parytet, newsteiners[i]);
21778 parytet = (triface *) fastlookup(cavetetlist, 0);
21779 setpoint2tet(newsteiners[i], (tetrahedron) (parytet->tet));
21781 if (steinerleft > 0) steinerleft--;
21785 for (j = 0; j < caveshlist->objects; j++) {
21787 parysh = (face *) fastlookup(caveshlist, j);
21788 stpivot(*parysh, neightet);
21791 dissolve(neightet);
21792 tsdissolve(neightet);
21795 cavetetlist->restart();
21796 caveshlist->restart();
21798 cavesegshlist->restart();
21800 if (vt == FREESEGVERTEX) {
21801 spivot(rightseg, parentsh);
21802 splitseg = &rightseg;
21804 if (sdest(parentsh) == steinerpt) {
21805 senextself(parentsh);
21806 }
else if (sapex(parentsh) == steinerpt) {
21807 senext2self(parentsh);
21811 sremovevertex(steinerpt, &parentsh, splitseg, slawson);
21813 if (vt == FREESEGVERTEX) {
21815 rightseg.shver = 0;
21820 for (i = 0; i < caveshbdlist->objects; i++) {
21821 parysh = (face *) fastlookup(caveshbdlist, i);
21827 maketetrahedron(&newtet);
21828 maketetrahedron(&neightet);
21829 setvertices(newtet, pa, pb, pc, dummypoint);
21830 setvertices(neightet, pb, pa, pc, dummypoint);
21831 bond(newtet, neightet);
21832 tsbond(newtet, newsh);
21834 tsbond(neightet, newsh);
21837 hullsize += (caveshbdlist->objects * 2l);
21839 if (vt == FREESEGVERTEX) {
21841 spivot(rightseg, parentsh);
21844 if (sorg(spinsh) != lpt) sesymself(spinsh);
21846 stpivot(spinsh, newtet);
21847 tssbond1(newtet, rightseg);
21849 spivot(spinsh, neighsh);
21850 if (sorg(neighsh) != lpt) sesymself(neighsh);
21851 sesymself(neighsh);
21852 stpivot(neighsh, neightet);
21853 tssbond1(neightet, rightseg);
21854 sstbond1(rightseg, neightet);
21857 esymself(neightet);
21859 bond(newtet, neightet);
21861 spivotself(spinsh);
21862 if (spinsh.sh == parentsh.sh)
break;
21867 for (i = 0; i < caveshbdlist->objects; i++) {
21868 parysh = (face *) fastlookup(caveshbdlist, i);
21872 for (k = 0; k < 2; k++) {
21873 stpivot(newsh, newtet);
21874 for (j = 0; j < 3; j++) {
21876 esym(newtet, newface);
21877 if (newface.tet[newface.ver & 3] == NULL) {
21879 sspivot(newsh, checkseg);
21880 if (checkseg.sh != NULL) {
21882 tssbond1(newtet, checkseg);
21883 sstbond1(checkseg, newtet);
21885 spivot(newsh, neighsh);
21886 if (neighsh.sh != NULL) {
21888 if (sorg(neighsh) != sdest(newsh)) sesymself(neighsh);
21889 stpivot(neighsh, neightet);
21890 if (sinfected(neighsh)) {
21891 esymself(neightet);
21894 spintet = neightet;
21896 esym(spintet, searchtet);
21897 fsym(searchtet, spintet);
21898 if (spintet.tet == NULL)
break;
21901 neightet = searchtet;
21906 sstpivot1(checkseg, neightet);
21907 if (org(neightet) != sdest(newsh)) esymself(neightet);
21909 spintet = neightet;
21911 esym(spintet, searchtet);
21912 fsym(searchtet, spintet);
21913 if (spintet.tet == NULL)
break;
21916 neightet = searchtet;
21918 pc = apex(newface);
21919 if (apex(neightet) == steinerpt) {
21922 caveoldtetlist->newindex((
void **) &parytet);
21923 *parytet = neightet;
21926 fnextself(neightet);
21928 if (pc == dummypoint) {
21929 if (apex(neightet) != dummypoint) {
21930 setapex(newface, apex(neightet));
21936 bond(newface, neightet);
21946 for (i = 0; i < caveshbdlist->objects; i++) {
21947 parysh = (face *) fastlookup(caveshbdlist, i);
21948 suninfect(*parysh);
21950 caveshbdlist->restart();
21952 if (caveoldtetlist->objects > 0l) {
21954 for (i = 0; i < caveoldtetlist->objects; i++) {
21955 parytet = (triface *) fastlookup(caveoldtetlist, i);
21956 tetrahedrondealloc(parytet->tet);
21959 hullsize -= caveoldtetlist->objects;
21960 caveoldtetlist->restart();
21963 setpointtype(steinerpt, UNUSEDVERTEX);
21965 if (vt == FREESEGVERTEX) {
21970 if (steinerleft > 0) steinerleft++;
21974 int steinercount = 0;
21976 int bak_fliplinklevel = b->fliplinklevel;
21977 b->fliplinklevel = 100000;
21980 for (i = 0; i < n; i++) {
21981 if (newsteiners[i] != NULL) {
21982 if (!removevertexbyflips(newsteiners[i])) {
21983 if (b->supsteiner_level > 0) {
21985 subvertstack->newindex((
void **) &parypt);
21986 *parypt = newsteiners[i];
21993 b->fliplinklevel = bak_fliplinklevel;
21995 if (steinercount > 0) {
21996 if (b->verbose > 2) {
21997 printf(
" Added %d interior Steiner points.\n", steinercount);
22001 delete [] newsteiners;
22017 int tetgenmesh::suppresssteinerpoints()
22021 printf(
"Suppressing Steiner points ...\n");
22024 point rempt, *parypt;
22026 int bak_fliplinklevel = b->fliplinklevel;
22027 b->fliplinklevel = 100000;
22028 int suppcount = 0, remcount = 0;
22032 for (i = 0; i < subvertstack->objects; i++) {
22033 parypt = (point *) fastlookup(subvertstack, i);
22035 if (pointtype(rempt) != UNUSEDVERTEX) {
22036 if ((pointtype(rempt) == FREESEGVERTEX) ||
22037 (pointtype(rempt) == FREEFACETVERTEX)) {
22038 if (suppressbdrysteinerpoint(rempt)) {
22045 if (suppcount > 0) {
22047 printf(
" Suppressed %d boundary Steiner points.\n", suppcount);
22051 if (b->supsteiner_level > 0) {
22052 for (i = 0; i < subvertstack->objects; i++) {
22053 parypt = (point *) fastlookup(subvertstack, i);
22055 if (pointtype(rempt) != UNUSEDVERTEX) {
22056 if (pointtype(rempt) == FREEVOLVERTEX) {
22057 if (removevertexbyflips(rempt)) {
22065 if (remcount > 0) {
22067 printf(
" Removed %d interior Steiner points.\n", remcount);
22071 b->fliplinklevel = bak_fliplinklevel;
22073 if (b->supsteiner_level > 1) {
22079 int smtcount, count, ivcount;
22083 opm.max_min_volume = 1;
22084 opm.numofsearchdirs = 20;
22085 opm.searchstep = 0.001;
22098 for (i = 0; i < subvertstack->objects; i++) {
22099 parypt = (point *) fastlookup(subvertstack, i);
22101 if (pointtype(rempt) == FREEVOLVERTEX) {
22102 getvertexstar(1, rempt, cavetetlist, NULL, NULL);
22104 for (j = 0; j < cavetetlist->objects; j++) {
22105 parytet = (triface *) fastlookup(cavetetlist, j);
22106 ppt = (point *) &(parytet->tet[4]);
22107 ori = orient3dfast(ppt[1], ppt[0], ppt[2], ppt[3]);
22111 if (opm.initval > ori) opm.initval = ori;
22114 if (smoothpoint(rempt, cavetetlist, 1, &opm)) {
22117 if (opm.imprval <= 0.0) {
22120 cavetetlist->restart();
22139 if (opm.maxiter > 0) {
22141 opm.numofsearchdirs = 30;
22142 opm.searchstep = 0.0001;
22152 printf(
"BUG Report! The mesh contain inverted elements.\n");
22156 if (smtcount > 0) {
22157 printf(
" Smoothed %d Steiner points.\n", smtcount);
22162 subvertstack->restart();
22173 void tetgenmesh::recoverboundary(clock_t& tv)
22175 arraypool *misseglist, *misshlist;
22176 arraypool *bdrysteinerptlist;
22177 face searchsh, *parysh;
22178 face searchseg, *paryseg;
22179 point rempt, *parypt;
22185 long bak_segref_count, bak_facref_count, bak_volref_count;
22188 printf(
"Recovering boundaries...\n");
22193 printf(
" Recovering segments.\n");
22197 checksubsegflag = 1;
22199 misseglist =
new arraypool(
sizeof(face), 8);
22200 bdrysteinerptlist =
new arraypool(
sizeof(point), 8);
22203 subsegs->traversalinit();
22204 for (i = 0; i < subsegs->items; i++) {
22205 s = randomnation(i + 1);
22207 subsegstack->newindex((
void **) &paryseg);
22208 *paryseg = * (face *) fastlookup(subsegstack, s);
22210 searchseg.sh = shellfacetraverse(subsegs);
22211 paryseg = (face *) fastlookup(subsegstack, s);
22212 *paryseg = searchseg;
22216 ms = subsegs->items;
22218 if (b->fliplinklevel < 0) {
22219 autofliplinklevel = 1;
22224 recoversegments(misseglist, 0, 0);
22226 if (misseglist->objects > 0) {
22227 if (b->fliplinklevel >= 0) {
22230 if (misseglist->objects >= ms) {
22235 b->fliplinklevel = 100000;
22238 ms = misseglist->objects;
22243 for (i = 0; i < misseglist->objects; i++) {
22244 subsegstack->newindex((
void **) &paryseg);
22245 *paryseg = * (face *) fastlookup(misseglist, i);
22247 misseglist->restart();
22248 autofliplinklevel+=b->fliplinklevelinc;
22257 printf(
" %ld (%ld) segments are recovered (missing).\n",
22258 subsegs->items - misseglist->objects, misseglist->objects);
22261 if (misseglist->objects > 0) {
22263 while (misseglist->objects > 0) {
22264 ms = misseglist->objects;
22265 for (i = 0; i < misseglist->objects; i++) {
22266 subsegstack->newindex((
void **) &paryseg);
22267 *paryseg = * (face *) fastlookup(misseglist, i);
22269 misseglist->restart();
22271 recoversegments(misseglist, 1, 0);
22273 if (misseglist->objects < ms) {
22281 printf(
" %ld (%ld) segments are recovered (missing).\n",
22282 subsegs->items - misseglist->objects, misseglist->objects);
22286 if (misseglist->objects > 0) {
22289 while (misseglist->objects > 0) {
22290 ms = misseglist->objects;
22291 for (i = 0; i < misseglist->objects; i++) {
22292 subsegstack->newindex((
void **) &paryseg);
22293 *paryseg = * (face *) fastlookup(misseglist, i);
22295 misseglist->restart();
22297 recoversegments(misseglist, 1, 1);
22299 if (misseglist->objects < ms) {
22307 printf(
" Added %ld Steiner points in volume.\n", st_volref_count);
22311 if (misseglist->objects > 0) {
22314 long bak_inpoly_count = st_volref_count;
22315 for (i = 0; i < misseglist->objects; i++) {
22316 subsegstack->newindex((
void **) &paryseg);
22317 *paryseg = * (face *) fastlookup(misseglist, i);
22319 misseglist->restart();
22321 recoversegments(misseglist, 1, 2);
22324 printf(
" Added %ld Steiner points in segments.\n", st_segref_count);
22325 if (st_volref_count > bak_inpoly_count) {
22326 printf(
" Added another %ld Steiner points in volume.\n",
22327 st_volref_count - bak_inpoly_count);
22333 if (st_segref_count > 0) {
22335 bak_segref_count = st_segref_count;
22336 bak_volref_count = st_volref_count;
22337 for (i = 0; i < subvertstack->objects; i++) {
22339 parypt = (point *) fastlookup(subvertstack, i);
22341 if (!removevertexbyflips(rempt)) {
22343 bdrysteinerptlist->newindex((
void **) &parypt);
22348 if (st_segref_count < bak_segref_count) {
22349 if (bak_volref_count < st_volref_count) {
22350 printf(
" Suppressed %ld Steiner points in segments.\n",
22351 st_volref_count - bak_volref_count);
22353 if ((st_segref_count + (st_volref_count - bak_volref_count)) <
22354 bak_segref_count) {
22355 printf(
" Removed %ld Steiner points in segments.\n",
22357 (st_segref_count + (st_volref_count - bak_volref_count)));
22361 subvertstack->restart();
22368 printf(
" Recovering facets.\n");
22372 checksubfaceflag = 1;
22374 misshlist =
new arraypool(
sizeof(face), 8);
22377 subfaces->traversalinit();
22378 for (i = 0; i < subfaces->items; i++) {
22379 s = randomnation(i + 1);
22381 subfacstack->newindex((
void **) &parysh);
22382 *parysh = * (face *) fastlookup(subfacstack, s);
22384 searchsh.sh = shellfacetraverse(subfaces);
22385 parysh = (face *) fastlookup(subfacstack, s);
22386 *parysh = searchsh;
22389 ms = subfaces->items;
22391 b->fliplinklevel = -1;
22392 if (b->fliplinklevel < 0) {
22393 autofliplinklevel = 1;
22397 recoversubfaces(misshlist, 0);
22399 if (misshlist->objects > 0) {
22400 if (b->fliplinklevel >= 0) {
22403 if (misshlist->objects >= ms) {
22408 b->fliplinklevel = 100000;
22411 ms = misshlist->objects;
22416 for (i = 0; i < misshlist->objects; i++) {
22417 subfacstack->newindex((
void **) &parysh);
22418 *parysh = * (face *) fastlookup(misshlist, i);
22420 misshlist->restart();
22421 autofliplinklevel+=b->fliplinklevelinc;
22430 printf(
" %ld (%ld) subfaces are recovered (missing).\n",
22431 subfaces->items - misshlist->objects, misshlist->objects);
22434 if (misshlist->objects > 0) {
22436 for (i = 0; i < misshlist->objects; i++) {
22437 subfacstack->newindex((
void **) &parysh);
22438 *parysh = * (face *) fastlookup(misshlist, i);
22440 misshlist->restart();
22442 recoversubfaces(NULL, 1);
22445 printf(
" Added %ld Steiner points in facets.\n", st_facref_count);
22450 if (st_facref_count > 0) {
22452 bak_facref_count = st_facref_count;
22453 for (i = 0; i < subvertstack->objects; i++) {
22455 parypt = (point *) fastlookup(subvertstack, i);
22457 if (!removevertexbyflips(*parypt)) {
22459 bdrysteinerptlist->newindex((
void **) &parypt);
22464 if (st_facref_count < bak_facref_count) {
22465 printf(
" Removed %ld Steiner points in facets.\n",
22466 bak_facref_count - st_facref_count);
22469 subvertstack->restart();
22473 if (bdrysteinerptlist->objects > 0) {
22475 printf(
" %ld Steiner points remained in boundary.\n",
22476 bdrysteinerptlist->objects);
22482 totalworkmemory += (misseglist->totalmemory + misshlist->totalmemory +
22483 bdrysteinerptlist->totalmemory);
22485 delete bdrysteinerptlist;
22506 void tetgenmesh::carveholes()
22508 arraypool *tetarray, *hullarray;
22509 triface tetloop, neightet, *parytet, *parytet1;
22510 triface *regiontets = NULL;
22511 face checksh, *parysh;
22513 point ptloop, *parypt;
22519 printf(
"Marking exterior tetrahedra ...\n");
22521 printf(
"Removing exterior tetrahedra ...\n");
22526 tetarray =
new arraypool(
sizeof(triface), 10);
22527 hullarray =
new arraypool(
sizeof(triface), 10);
22530 tetrahedrons->traversalinit();
22532 tetloop.tet = alltetrahedrontraverse();
22533 while (tetloop.tet != (tetrahedron *) NULL) {
22534 if (ishulltet(tetloop)) {
22536 if (!issubface(tetloop)) {
22539 hullarray->newindex((
void **) &parytet);
22540 *parytet = tetloop;
22542 decode(tetloop.tet[3], neightet);
22543 if (!infected(neightet)) {
22545 tetarray->newindex((
void **) &parytet);
22546 *parytet = neightet;
22550 tetloop.tet = alltetrahedrontraverse();
22553 if (in->numberofholes > 0) {
22555 for (i = 0; i < 3 * in->numberofholes; i += 3) {
22557 neightet.tet = NULL;
22558 randomsample(&(in->holelist[i]), &neightet);
22559 if (locate(&(in->holelist[i]), &neightet) != OUTSIDE) {
22561 if (!infected(neightet)) {
22563 tetarray->newindex((
void **) &parytet);
22564 *parytet = neightet;
22566 if (!issubface(neightet)) {
22567 decode(neightet.tet[neightet.ver & 3], tetloop);
22568 if (!infected(tetloop)) {
22570 if (ishulltet(tetloop)) {
22571 hullarray->newindex((
void **) &parytet);
22573 tetarray->newindex((
void **) &parytet);
22575 *parytet = tetloop;
22580 decode(neightet.tet[neightet.ver & 3], tetloop);
22581 if (ishulltet(tetloop)) {
22584 if (!infected(tetloop)) {
22586 hullarray->newindex((
void **) &parytet);
22587 *parytet = tetloop;
22590 if (infected(tetloop)) {
22592 tspivot(neightet, checksh);
22594 subfacstack->newindex((
void **) &parysh);
22602 printf(
"Warning: The %d-th hole point ", i/3 + 1);
22603 printf(
"lies outside the convex hull.\n");
22609 if (b->hole_mesh && (b->hole_mesh_filename[0] != 0)) {
22612 char filebasename[256];
22613 strcpy(filebasename, b->hole_mesh_filename);
22615 if (!strcmp(&filebasename[strlen(filebasename) - 4],
".ele")) {
22616 filebasename[strlen(filebasename) - 4] =
'\0';
22619 bool hole_mesh_loaded =
false;
22621 if (io.load_node(filebasename)) {
22622 if (io.load_tet(filebasename)) {
22623 hole_mesh_loaded =
true;
22626 if (hole_mesh_loaded) {
22628 printf(
" Adding hole tets from the mesh %s\n", b->hole_mesh_filename);
22630 int count = 0, hcount = 0, scount = 0;
22631 int shift = io.firstnumber > 0 ? -1 : 0;
22632 double *p1, *p2, *p3, *p4;
22633 double searchpt[3];
22634 for (i = 0; i < io.numberoftetrahedra; i++) {
22635 int *idx = &(io.tetrahedronlist[i * 4]);
22636 p1 = &(io.pointlist[(idx[0]+shift)*3]);
22637 p2 = &(io.pointlist[(idx[1]+shift)*3]);
22638 p3 = &(io.pointlist[(idx[2]+shift)*3]);
22639 p4 = &(io.pointlist[(idx[3]+shift)*3]);
22640 for (j = 0; j < 3; j++) {
22641 searchpt[j] = (p1[j]+p2[j]+p3[j]+p4[j])/4.;
22644 neightet.tet = NULL;
22645 if (locate(searchpt, &neightet) != OUTSIDE) {
22647 if (!infected(neightet)) {
22649 tetarray->newindex((
void **) &parytet);
22650 *parytet = neightet;
22653 if (!issubface(neightet)) {
22654 decode(neightet.tet[neightet.ver & 3], tetloop);
22655 if (!infected(tetloop)) {
22657 if (ishulltet(tetloop)) {
22658 hullarray->newindex((
void **) &parytet);
22661 tetarray->newindex((
void **) &parytet);
22664 *parytet = tetloop;
22669 decode(neightet.tet[neightet.ver & 3], tetloop);
22670 if (ishulltet(tetloop)) {
22673 if (!infected(tetloop)) {
22675 hullarray->newindex((
void **) &parytet);
22676 *parytet = tetloop;
22680 if (infected(tetloop)) {
22682 tspivot(neightet, checksh);
22684 subfacstack->newindex((
void **) &parysh);
22693 printf(
" Added %d hole tets, %d hull tet, %d hole subfaces\n",
22694 count, hcount, scount);
22699 if (b->regionattrib && (in->numberofregions > 0)) {
22702 regiontets =
new triface[in->numberofregions];
22704 for (i = 0; i < 5 * in->numberofregions; i += 5) {
22706 neightet.tet = NULL;
22707 randomsample(&(in->regionlist[i]), &neightet);
22708 if (locate(&(in->regionlist[i]), &neightet) != OUTSIDE) {
22709 regiontets[i/5] = neightet;
22712 printf(
"Warning: The %d-th region point ", i/5+1);
22713 printf(
"lies outside the convex hull.\n");
22715 regiontets[i/5].tet = NULL;
22721 for (i = 0; i < tetarray->objects; i++) {
22722 parytet = (triface *) fastlookup(tetarray, i);
22723 j = (parytet->ver & 3);
22725 for (k = 1; k < 4; k++) {
22726 decode(parytet->tet[(j + k) % 4], neightet);
22728 if (!infected(neightet)) {
22730 if (!issubface(neightet)) {
22733 tetarray->newindex((
void **) &parytet1);
22734 *parytet1 = neightet;
22737 if (ishulltet(neightet)) {
22740 hullarray->newindex((
void **) &parytet1);
22741 *parytet1 = neightet;
22743 tspivot(neightet, checksh);
22746 subfacstack->newindex((
void **) &parysh);
22753 if (issubface(neightet)) {
22754 tspivot(neightet, checksh);
22755 if (!sinfected(checksh)) {
22757 subfacstack->newindex((
void **) &parysh);
22765 if (b->regionattrib && (in->numberofregions > 0)) {
22767 for (i = 0; i < in->numberofregions; i++) {
22768 if (infected(regiontets[i])) {
22770 printf(
"Warning: The %d-th region point ", i+1);
22771 printf(
"lies in the exterior of the domain.\n");
22773 regiontets[i].tet = NULL;
22782 points->traversalinit();
22783 ptloop = pointtraverse();
22784 while (ptloop != NULL) {
22785 if ((pointtype(ptloop) != UNUSEDVERTEX) &&
22786 (pointtype(ptloop) != DUPLICATEDVERTEX)) {
22787 decode(point2tet(ptloop), neightet);
22788 if (infected(neightet)) {
22789 cavetetvertlist->newindex((
void **) &parypt);
22792 if (b->nobisect && (b->supsteiner_level > 0)) {
22794 if (pointmark(ptloop) >
22795 (in->numberofpoints - (in->firstnumber ? 0 : 1))) {
22796 subvertstack->newindex((
void **) &parypt);
22801 ptloop = pointtraverse();
22804 if (!b->convex && (tetarray->objects > 0l)) {
22806 arraypool *newhullfacearray;
22807 triface hulltet, casface;
22808 face segloop, *paryseg;
22810 long delsegcount = 0l;
22814 subsegs->traversalinit();
22815 segloop.sh = shellfacetraverse(subsegs);
22816 while (segloop.sh != NULL) {
22817 sstpivot1(segloop, neightet);
22818 if (infected(neightet)) {
22819 subsegstack->newindex((
void **) &paryseg);
22820 *paryseg = segloop;
22822 segloop.sh = shellfacetraverse(subsegs);
22825 newhullfacearray =
new arraypool(
sizeof(triface), 10);
22828 for (i = 0; i < tetarray->objects; i++) {
22829 parytet = (triface *) fastlookup(tetarray, i);
22830 for (j = 0; j < 4; j++) {
22831 decode(parytet->tet[j], tetloop);
22832 if (!infected(tetloop)) {
22834 tspivot(tetloop, checksh);
22835 maketetrahedron(&hulltet);
22837 pb = dest(tetloop);
22838 pc = apex(tetloop);
22839 setvertices(hulltet, pb, pa, pc, dummypoint);
22840 bond(tetloop, hulltet);
22842 sesymself(checksh);
22843 tsbond(hulltet, checksh);
22845 for (k = 0; k < 3; k++) {
22846 if (issubseg(tetloop)) {
22847 tsspivot1(tetloop, checkseg);
22848 tssbond1(hulltet, checkseg);
22849 sstbond1(checkseg, hulltet);
22851 enextself(tetloop);
22852 eprevself(hulltet);
22855 setpoint2tet(pa, (tetrahedron) tetloop.tet);
22856 setpoint2tet(pb, (tetrahedron) tetloop.tet);
22857 setpoint2tet(pc, (tetrahedron) tetloop.tet);
22860 newhullfacearray->newindex((
void **) &parytet1);
22861 parytet1->tet = parytet->tet;
22868 for (i = 0; i < newhullfacearray->objects; i++) {
22869 parytet = (triface *) fastlookup(newhullfacearray, i);
22870 fsym(*parytet, neightet);
22872 fsym(neightet, hulltet);
22873 for (j = 0; j < 3; j++) {
22874 esym(hulltet, casface);
22875 if (casface.tet[casface.ver & 3] == NULL) {
22879 neightet = *parytet;
22881 fnextself(neightet);
22882 if (!infected(neightet))
break;
22884 if (!ishulltet(neightet)) {
22886 fsymself(neightet);
22887 esymself(neightet);
22890 bond(casface, neightet);
22892 enextself(hulltet);
22893 enextself(*parytet);
22897 if (subfacstack->objects > 0l) {
22901 face casingout, casingin;
22903 for (i = 0; i < subfacstack->objects; i++) {
22904 parysh = (face *) fastlookup(subfacstack, i);
22907 printf(
"Warning: Removed an exterior face (%d, %d, %d) #%d\n",
22908 pointmark(sorg(*parysh)), pointmark(sdest(*parysh)),
22909 pointmark(sapex(*parysh)), shellmark(*parysh));
22913 for (j = 0; j < 3; j++) {
22914 spivot(*parysh, casingout);
22915 sspivot(*parysh, checkseg);
22916 if (casingout.sh != NULL) {
22917 casingin = casingout;
22919 spivot(casingin, checksh);
22920 if (checksh.sh == parysh->sh)
break;
22921 casingin = checksh;
22923 if (casingin.sh != casingout.sh) {
22925 sbond1(casingin, casingout);
22928 sdissolve(casingout);
22930 if (checkseg.sh != NULL) {
22932 ssbond(casingout, checkseg);
22935 if (checkseg.sh != NULL) {
22937 if (delsegcount == 0) {
22939 printf(
"Warning: Removed an exterior segment (%d, %d) #%d\n",
22940 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)),
22941 shellmark(checkseg));
22944 shellfacedealloc(subsegs, checkseg.sh);
22948 senextself(*parysh);
22951 shellfacedealloc(subfaces, parysh->sh);
22954 printf(
" Deleted %ld subfaces.\n", subfacstack->objects);
22956 subfacstack->restart();
22959 if (subsegstack->objects > 0l) {
22960 for (i = 0; i < subsegstack->objects; i++) {
22961 paryseg = (face *) fastlookup(subsegstack, i);
22962 if (paryseg->sh && (paryseg->sh[3] != NULL)) {
22963 sstpivot1(*paryseg, neightet);
22964 if (infected(neightet)) {
22966 printf(
"Warning: Removed an exterior segment (%d, %d) #%d\n",
22967 pointmark(sorg(*paryseg)), pointmark(sdest(*paryseg)),
22968 shellmark(*paryseg));
22970 shellfacedealloc(subsegs, paryseg->sh);
22975 subsegstack->restart();
22978 if (delsegcount > 0) {
22980 printf(
" Deleted %ld segments.\n", delsegcount);
22984 if (cavetetvertlist->objects > 0l) {
22986 long delvertcount = unuverts;
22987 long delsteinercount = 0l;
22989 for (i = 0; i < cavetetvertlist->objects; i++) {
22990 parypt = (point *) fastlookup(cavetetvertlist, i);
22991 decode(point2tet(*parypt), neightet);
22992 if (infected(neightet)) {
22994 if (pointmark(*parypt) >
22995 (in->numberofpoints - (in->firstnumber ? 0 : 1))) {
22997 if (pointtype(*parypt) == FREESEGVERTEX) {
22999 }
else if (pointtype(*parypt) == FREEFACETVERTEX) {
23005 if (steinerleft > 0) steinerleft++;
23007 setpointtype(*parypt, UNUSEDVERTEX);
23013 if (unuverts > delvertcount) {
23014 if (delsteinercount > 0l) {
23015 if (unuverts > (delvertcount + delsteinercount)) {
23016 printf(
" Removed %ld exterior input vertices.\n",
23017 unuverts - delvertcount - delsteinercount);
23019 printf(
" Removed %ld exterior Steiner vertices.\n",
23022 printf(
" Removed %ld exterior input vertices.\n",
23023 unuverts - delvertcount);
23027 cavetetvertlist->restart();
23033 hullsize += (newhullfacearray->objects - hullarray->objects);
23036 for (i = 0; i < tetarray->objects; i++) {
23037 parytet = (triface *) fastlookup(tetarray, i);
23038 tetrahedrondealloc(parytet->tet);
23040 tetarray->restart();
23042 for (i = 0; i < hullarray->objects; i++) {
23043 parytet = (triface *) fastlookup(hullarray, i);
23044 tetrahedrondealloc(parytet->tet);
23046 hullarray->restart();
23048 delete newhullfacearray;
23051 if (b->convex && (tetarray->objects > 0l)) {
23053 int attrnum = numelemattrib - 1;
23055 for (i = 0; i < tetarray->objects; i++) {
23056 parytet = (triface *) fastlookup(tetarray, i);
23057 setelemattribute(parytet->tet, attrnum, -1);
23059 tetarray->restart();
23061 for (i = 0; i < hullarray->objects; i++) {
23062 parytet = (triface *) fastlookup(hullarray, i);
23063 uninfect(*parytet);
23065 hullarray->restart();
23067 if (subfacstack->objects > 0l) {
23068 for (i = 0; i < subfacstack->objects; i++) {
23069 parysh = (face *) fastlookup(subfacstack, i);
23070 suninfect(*parysh);
23072 subfacstack->restart();
23075 if (cavetetvertlist->objects > 0l) {
23076 cavetetvertlist->restart();
23080 if (b->regionattrib) {
23082 printf(
"Spreading region attributes.\n");
23085 int attr, maxattr = 0;
23086 int attrnum = numelemattrib - 1;
23089 int regioncount = 0;
23092 if (in->numberofregions > 0) {
23094 for (i = 0; i < 5 * in->numberofregions; i += 5) {
23095 if (regiontets[i/5].tet != NULL) {
23096 attr = (int) in->regionlist[i + 3];
23097 if (attr > maxattr) {
23100 volume = in->regionlist[i + 4];
23101 tetarray->restart();
23102 infect(regiontets[i/5]);
23103 tetarray->newindex((
void **) &parytet);
23104 *parytet = regiontets[i/5];
23106 for (j = 0; j < tetarray->objects; j++) {
23107 parytet = (triface *) fastlookup(tetarray, j);
23108 tetloop = *parytet;
23109 setelemattribute(tetloop.tet, attrnum, attr);
23110 if (b->varvolume) {
23111 setvolumebound(tetloop.tet, volume);
23113 for (k = 0; k < 4; k++) {
23114 decode(tetloop.tet[k], neightet);
23116 if (!infected(neightet)) {
23118 if (!issubface(neightet)) {
23120 tetarray->newindex((
void **) &parytet);
23121 *parytet = neightet;
23132 attr = maxattr + 1;
23133 tetrahedrons->traversalinit();
23134 tetloop.tet = tetrahedrontraverse();
23135 while (tetloop.tet != (tetrahedron *) NULL) {
23136 if (!infected(tetloop)) {
23138 tetarray->restart();
23140 tetarray->newindex((
void **) &parytet);
23141 *parytet = tetloop;
23143 for (j = 0; j < tetarray->objects; j++) {
23144 parytet = (triface *) fastlookup(tetarray, j);
23145 tetloop = *parytet;
23146 setelemattribute(tetloop.tet, attrnum, attr);
23147 for (k = 0; k < 4; k++) {
23148 decode(tetloop.tet[k], neightet);
23150 if (!infected(neightet)) {
23152 if (!issubface(neightet)) {
23154 tetarray->newindex((
void **) &parytet);
23155 *parytet = neightet;
23163 tetloop.tet = tetrahedrontraverse();
23168 tetrahedrons->traversalinit();
23169 tetloop.tet = tetrahedrontraverse();
23170 while (tetloop.tet != (tetrahedron *) NULL) {
23172 tetloop.tet = tetrahedrontraverse();
23177 if (regioncount > 1) {
23178 printf(
" Found %d subdomains.\n", regioncount);
23180 printf(
" Found %d domain.\n", regioncount);
23185 if (regiontets != NULL) {
23186 delete [] regiontets;
23196 tetrahedrons->traversalinit();
23198 tetloop.tet = alltetrahedrontraverse();
23199 while (tetloop.tet != (tetrahedron *) NULL) {
23200 if ((point) tetloop.tet[7] == dummypoint) {
23201 fsym(tetloop, neightet);
23202 flippush(flipstack, &neightet);
23204 tetloop.tet = alltetrahedrontraverse();
23207 flipconstraints fc;
23209 long sliver_peel_count = lawsonflip3d(&fc);
23211 if (sliver_peel_count > 0l) {
23213 printf(
" Removed %ld hull slivers.\n", sliver_peel_count);
23216 unflipqueue->restart();
23225 int tetgenmesh::search_face(point pi, point pj, point pk, triface &tetloop)
23236 t.ver = t1.ver = 0;
23237 tetrahedrons->traversalinit();
23238 t.tet = tetrahedrontraverse();
23239 while (t.tet != NULL) {
23240 pts = (point *) t.tet;
23242 if (pinfected(pts[4])) pcount++;
23243 if (pinfected(pts[5])) pcount++;
23244 if (pinfected(pts[6])) pcount++;
23245 if (pinfected(pts[7])) pcount++;
23249 for (t.ver = 0; t.ver < 4; t.ver++) {
23251 if (!pinfected(toppo))
break;
23254 for (ii = 0; ii < 3; ii++) {
23255 if (org(t) == pi)
break;
23258 if (dest(t) == pj) {
23265 t.tet = tetrahedrontraverse();
23272 if (t.tet != NULL) {
23280 int tetgenmesh::search_edge(point p0, point p1, triface &tetloop)
23285 tetrahedrons->traversalinit();
23286 t.tet = tetrahedrontraverse();
23287 while (t.tet != NULL) {
23288 for (ii = 0; ii < 6; ii++) {
23289 t.ver = edge2ver[ii];
23290 if (((org(t) == p0) && (dest(t) == p1)) ||
23291 ((org(t) == p1) && (dest(t) == p0))) {
23297 t.tet = tetrahedrontraverse();
23300 tetloop.tet = NULL;
23310 void tetgenmesh::reconstructmesh()
23312 tetrahedron *ver2tetarray;
23313 point *idx2verlist;
23314 triface tetloop, checktet, prevchktet;
23315 triface hulltet, face1, face2;
23317 face subloop, neighsh, nextsh;
23321 REAL ori, attrib, volume;
23322 REAL cosang_tol, cosang;
23324 int eextras, marker = 0;
23330 printf(
"Reconstructing mesh ...\n");
23335 if (!(in->numberoftetrahedronattributes > 0)) {
23336 terminatetetgen(
this, 2);
23344 makeindex2pointmap(idx2verlist);
23346 if (in->firstnumber == 1) {
23347 idx2verlist[0] = dummypoint;
23351 ver2tetarray =
new tetrahedron[in->numberofpoints + 1];
23352 unuverts = in->numberofpoints;
23354 for (i = in->firstnumber; i < in->numberofpoints + in->firstnumber; i++) {
23355 ver2tetarray[i] = NULL;
23359 for (i = 0; i < in->numberoftetrahedra; i++) {
23361 idx = i * in->numberofcorners;
23362 for (j = 0; j < 4; j++) {
23363 p[j] = idx2verlist[in->tetrahedronlist[idx++]];
23364 if (pointtype(p[j]) == UNUSEDVERTEX) {
23365 setpointtype(p[j], VOLVERTEX);
23370 ori = orient3d(p[0], p[1], p[2], p[3]);
23373 q[0] = p[0]; p[0] = p[1]; p[1] = q[0];
23374 }
else if (ori == 0.0) {
23376 printf(
"Warning: Tet #%d is degenerate.\n", i + in->firstnumber);
23380 maketetrahedron(&tetloop);
23381 setvertices(tetloop, p[0], p[1], p[2], p[3]);
23383 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
23384 idx = i * in->numberoftetrahedronattributes;
23385 attrib = in->tetrahedronattributelist[idx + j];
23386 setelemattribute(tetloop.tet, j, attrib);
23390 if (b->varvolume) {
23391 if (in->tetrahedronvolumelist != (REAL *) NULL) {
23392 volume = in->tetrahedronvolumelist[i];
23396 setvolumebound(tetloop.tet, volume);
23399 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23400 p[3] = oppo(tetloop);
23402 idx = pointmark(p[3]);
23403 tptr = ver2tetarray[idx];
23405 tetloop.tet[8 + tetloop.ver] = tptr;
23407 ver2tetarray[idx] = encode(tetloop);
23408 decode(tptr, checktet);
23409 if (checktet.tet != NULL) {
23410 p[0] = org(tetloop);
23411 p[1] = dest(tetloop);
23412 p[2] = apex(tetloop);
23413 prevchktet = tetloop;
23415 q[0] = org(checktet);
23416 q[1] = dest(checktet);
23417 q[2] = apex(checktet);
23420 for (j = 0; j < 3; j++) {
23422 esym(checktet, face2);
23423 if (face2.tet[face2.ver & 3] == NULL) {
23425 if (q[k] == p[0]) {
23426 if (q[j] == p[1]) {
23428 esym(tetloop, face1);
23429 bond(face1, face2);
23433 if (q[k] == p[1]) {
23434 if (q[j] == p[2]) {
23436 enext(tetloop, face1);
23438 bond(face1, face2);
23442 if (q[k] == p[2]) {
23443 if (q[j] == p[0]) {
23445 eprev(tetloop, face1);
23447 bond(face1, face2);
23454 enextself(checktet);
23457 tptr = checktet.tet[8 + checktet.ver];
23458 if (bondflag == 3) {
23461 prevchktet.tet[8 + prevchktet.ver] = tptr;
23464 prevchktet = checktet;
23466 decode(tptr, checktet);
23467 }
while (checktet.tet != NULL);
23473 recenttet = tetloop;
23477 hullsize = tetrahedrons->items;
23479 tetrahedrons->traversalinit();
23480 tetloop.tet = tetrahedrontraverse();
23481 while (tetloop.tet != (tetrahedron *) NULL) {
23482 tptr = encode(tetloop);
23483 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23484 if (tetloop.tet[tetloop.ver] == NULL) {
23486 maketetrahedron(&hulltet);
23487 p[0] = org(tetloop);
23488 p[1] = dest(tetloop);
23489 p[2] = apex(tetloop);
23490 setvertices(hulltet, p[1], p[0], p[2], dummypoint);
23491 bond(tetloop, hulltet);
23493 for (j = 0; j < 3; j++) {
23494 fsym(hulltet, face2);
23496 if (face2.tet == NULL)
break;
23498 if (apex(face2) == dummypoint)
break;
23501 if (face2.tet != NULL) {
23503 esym(hulltet, face1);
23504 bond(face1, face2);
23506 enextself(hulltet);
23510 setpoint2tet((point) (tetloop.tet[4 + tetloop.ver]), tptr);
23512 tetloop.tet[8 + tetloop.ver] = NULL;
23514 tetloop.tet = tetrahedrontraverse();
23517 hullsize = tetrahedrons->items - hullsize;
23520 if (in->trifacelist != NULL) {
23522 for (i = 0; i < in->numberoftrifaces; i++) {
23524 if (in->trifacemarkerlist != NULL) {
23525 marker = in->trifacemarkerlist[i];
23532 for (j = 0; j < 3; j++) {
23533 p[j] = idx2verlist[in->trifacelist[idx++]];
23539 for (j = 0; j < 3; j++) {
23540 decode(point2tet(p[j]), checktet);
23541 if (checktet.tet == NULL)
break;
23543 if ((j == 3) && getedge(p[0], p[1], &checktet)) {
23544 tetloop = checktet;
23545 q[2] = apex(checktet);
23547 if (apex(tetloop) == p[2]) {
23550 tspivot(tetloop, neighsh);
23551 if (neighsh.sh != NULL) {
23560 fnextself(tetloop);
23561 if (apex(tetloop) == q[2])
break;
23565 if (neighsh.sh == NULL) {
23566 if (b->verbose > 1) {
23567 printf(
"Warning: Searching subface #%d [%d,%d,%d] mark=%d.\n",
23568 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]),
23569 pointmark(p[2]), marker);
23572 if (search_face(p[0], p[1], p[2], tetloop)) {
23579 makeshellface(subfaces, &subloop);
23580 setshvertices(subloop, p[0], p[1], p[2]);
23582 sptr = sencode(subloop);
23583 for (j = 0; j < 3; j++) {
23584 setpointtype(p[j], FACETVERTEX);
23585 setpoint2sh(p[j], sptr);
23587 setshellmark(subloop, marker);
23589 tsbond(tetloop, subloop);
23591 sesymself(subloop);
23592 tsbond(tetloop, subloop);
23594 if (neighsh.sh != NULL) {
23596 setshellmark(neighsh, marker);
23599 printf(
"Warning: Subface #%d [%d,%d,%d] mark=%d is not found.\n",
23600 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]),
23601 pointmark(p[2]), marker);
23612 eextras = in->numberoftetrahedronattributes;
23613 tetrahedrons->traversalinit();
23614 tetloop.tet = tetrahedrontraverse();
23615 while (tetloop.tet != (tetrahedron *) NULL) {
23616 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
23617 tspivot(tetloop, neighsh);
23618 if (neighsh.sh == NULL) {
23620 fsym(tetloop, checktet);
23621 if (ishulltet(checktet)) {
23628 if (elemattribute(tetloop.tet, eextras - 1) !=
23629 elemattribute(checktet.tet, eextras - 1)) {
23636 makeshellface(subfaces, &subloop);
23637 p[0] = org(tetloop);
23638 p[1] = dest(tetloop);
23639 p[2] = apex(tetloop);
23640 setshvertices(subloop, p[0], p[1], p[2]);
23642 sptr = sencode(subloop);
23643 for (j = 0; j < 3; j++) {
23644 setpointtype(p[j], FACETVERTEX);
23645 setpoint2sh(p[j], sptr);
23647 setshellmark(subloop, -1);
23649 tsbond(tetloop, subloop);
23650 sesymself(subloop);
23651 tsbond(checktet, subloop);
23655 tetloop.tet = tetrahedrontraverse();
23659 subfaces->traversalinit();
23661 subloop.sh = shellfacetraverse(subfaces);
23662 while (subloop.sh != (shellface *) NULL) {
23663 for (i = 0; i < 3; i++) {
23664 spivot(subloop, neighsh);
23665 if (neighsh.sh == NULL) {
23668 stpivot(subloop, tetloop);
23669 q[2] = apex(tetloop);
23672 fnextself(tetloop);
23673 tspivot(tetloop, nextsh);
23674 if (nextsh.sh != NULL) {
23676 if (nextsh.sh != neighsh.sh) {
23678 sbond1(neighsh, nextsh);
23682 if (apex(tetloop) == q[2]) {
23687 senextself(subloop);
23689 subloop.sh = shellfacetraverse(subfaces);
23694 if (in->edgelist != NULL) {
23696 for (i = 0; i < in->numberofedges; i++) {
23698 if (in->edgemarkerlist != NULL) {
23699 marker = in->edgemarkerlist[i];
23707 for (j = 0; j < 2; j++) {
23708 p[j] = idx2verlist[in->edgelist[idx++]];
23711 for (j = 0; j < 2; j++) {
23712 decode(point2tet(p[j]), checktet);
23713 if (checktet.tet == NULL)
break;
23718 if (getedge(p[0], p[1], &checktet)) {
23721 if (b->verbose > 1) {
23722 printf(
"Warning: Searching segment #%d [%d,%d] mark=%d.\n",
23723 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]), marker);
23726 if (search_edge(p[0], p[1], checktet)) {
23731 if (bondflag > 0) {
23733 makeshellface(subsegs, &segloop);
23734 setshvertices(segloop, p[0], p[1], NULL);
23736 sptr = sencode(segloop);
23737 for (j = 0; j < 2; j++) {
23738 setpointtype(p[j], RIDGEVERTEX);
23739 setpoint2sh(p[j], sptr);
23741 setshellmark(segloop, marker);
23743 tetloop = checktet;
23744 q[2] = apex(checktet);
23747 tssbond1(tetloop, segloop);
23748 tspivot(tetloop, subloop);
23749 if (subloop.sh != NULL) {
23750 ssbond1(subloop, segloop);
23751 sbond1(segloop, subloop);
23753 fnextself(tetloop);
23754 if (apex(tetloop) == q[2])
break;
23757 sstbond1(segloop, tetloop);
23760 printf(
"Warning: Segment #%d [%d,%d] is missing.\n",
23761 i + in->firstnumber, pointmark(p[0]), pointmark(p[1]));
23772 cosang_tol = cos(b->facet_separate_ang_tol / 180.0 * PI);
23773 subfaces->traversalinit();
23775 subloop.sh = shellfacetraverse(subfaces);
23776 while (subloop.sh != (shellface *) NULL) {
23777 for (i = 0; i < 3; i++) {
23778 sspivot(subloop, segloop);
23779 if (segloop.sh == NULL) {
23787 spivotself(nextsh);
23788 if (nextsh.sh == subloop.sh)
break;
23792 p[0] = sorg(subloop);
23793 p[1] = sdest(subloop);
23796 spivot(subloop, neighsh);
23797 if (shellmark(subloop) != shellmark(neighsh)) {
23799 p[0] = sorg(subloop);
23800 p[1] = sdest(subloop);
23805 p[0] = sorg(subloop);
23806 p[1] = sdest(subloop);
23807 p[2] = sapex(subloop);
23808 p[3] = sapex(neighsh);
23809 facenormal(p[0], p[1], p[2], n1, 1, NULL);
23810 facenormal(p[0], p[1], p[3], n2, 1, NULL);
23811 cosang = dot(n1, n2) / (sqrt(dot(n1, n1)) * sqrt(dot(n2, n2)));
23813 if (cosang > 1.0) cosang = 1.0;
23814 else if (cosang < -1.0) cosang = -1.0;
23815 if (cosang > cosang_tol) {
23823 makeshellface(subsegs, &segloop);
23824 setshvertices(segloop, p[0], p[1], NULL);
23826 sptr = sencode(segloop);
23827 for (j = 0; j < 2; j++) {
23828 setpointtype(p[j], RIDGEVERTEX);
23829 setpoint2sh(p[j], sptr);
23831 setshellmark(segloop, -1);
23833 stpivot(subloop, tetloop);
23834 q[2] = apex(tetloop);
23836 tssbond1(tetloop, segloop);
23837 tspivot(tetloop, neighsh);
23838 if (neighsh.sh != NULL) {
23839 ssbond1(neighsh, segloop);
23841 fnextself(tetloop);
23842 if (apex(tetloop) == q[2])
break;
23845 sstbond1(segloop, tetloop);
23846 sbond1(segloop, subloop);
23849 senextself(subloop);
23851 subloop.sh = shellfacetraverse(subfaces);
23855 insegments = subsegs->items;
23857 if (!b->nobisect || checkconstraints) {
23862 face* segperverlist;
23864 face parentseg, nextseg;
23866 REAL area, len, l1, l2;
23869 makepoint2submap(subsegs, idx2seglist, segperverlist);
23871 points->traversalinit();
23872 point ptloop = pointtraverse();
23873 while (ptloop != NULL) {
23874 vt = pointtype(ptloop);
23875 if (vt == VOLVERTEX) {
23876 setpointtype(ptloop, FREEVOLVERTEX);
23878 }
else if (vt == FACETVERTEX) {
23879 setpointtype(ptloop, FREEFACETVERTEX);
23881 }
else if (vt == RIDGEVERTEX) {
23882 idx = pointmark(ptloop) - in->firstnumber;
23883 if ((idx2seglist[idx + 1] - idx2seglist[idx]) == 2) {
23884 i = idx2seglist[idx];
23885 parentseg = segperverlist[i];
23886 nextseg = segperverlist[i + 1];
23887 sesymself(nextseg);
23888 p[0] = sorg(nextseg);
23889 p[1] = sdest(parentseg);
23891 len = distance(p[0], p[1]);
23892 l1 = distance(p[0], ptloop);
23893 l2 = distance(ptloop, p[1]);
23894 if (((l1 + l2 - len) / len) < b->epsilon) {
23896 setpointtype(ptloop, FREESEGVERTEX);
23898 senextself(nextseg);
23899 senext2self(parentseg);
23900 sbond(nextseg, parentseg);
23905 ptloop = pointtraverse();
23909 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
23911 for (i = 0; i < in->numberoffacetconstraints; i++) {
23912 fmarker = (int) in->facetconstraintlist[i * 2];
23913 area = in->facetconstraintlist[i * 2 + 1];
23914 subfaces->traversalinit();
23915 subloop.sh = shellfacetraverse(subfaces);
23916 while (subloop.sh != NULL) {
23917 if (shellmark(subloop) == fmarker) {
23918 setareabound(subloop, area);
23920 subloop.sh = shellfacetraverse(subfaces);
23926 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
23929 for (i = 0; i < in->numberofsegmentconstraints; i++) {
23930 e1 = (int) in->segmentconstraintlist[i * 3];
23931 e2 = (
int) in->segmentconstraintlist[i * 3 + 1];
23932 len = in->segmentconstraintlist[i * 3 + 2];
23934 idx = e1 - in->firstnumber;
23935 for (j = idx2seglist[idx]; j < idx2seglist[idx + 1]; j++) {
23936 parentseg = segperverlist[j];
23937 if (pointmark(sdest(parentseg)) == e2) {
23938 setareabound(parentseg, len);
23945 delete [] idx2seglist;
23946 delete [] segperverlist;
23951 checksubsegflag = 1;
23952 checksubfaceflag = 1;
23954 delete [] idx2verlist;
23955 delete [] ver2tetarray;
23970 int tetgenmesh::scoutpoint(point searchpt, triface *searchtet,
int randflag)
23972 point pa, pb, pc, pd;
23973 enum locateresult loc = OUTSIDE;
23974 REAL vol, ori1, ori2 = 0, ori3 = 0, ori4 = 0;
23980 randomsample(searchpt, searchtet);
23982 if (searchtet->tet == NULL) {
23983 *searchtet = recenttet;
23986 loc = locate(searchpt, searchtet);
23988 if (loc == OUTSIDE) {
23995 pa = org(*searchtet);
23996 pb = dest(*searchtet);
23997 pc = apex(*searchtet);
23998 vol = triarea(pa, pb, pc);
23999 ori1 = orient3dfast(pa, pb, pc, searchpt);
24000 if (fabs(ori1 / vol) < b->epsilon) {
24002 fsymself(*searchtet);
24006 if (loc != OUTSIDE) {
24008 pa = org(*searchtet);
24009 pb = dest(*searchtet);
24010 pc = apex(*searchtet);
24011 pd = oppo(*searchtet);
24012 vol = orient3dfast(pa, pb, pc, pd);
24013 ori1 = orient3dfast(pa, pb, pc, searchpt);
24014 ori2 = orient3dfast(pb, pa, pd, searchpt);
24015 ori3 = orient3dfast(pc, pb, pd, searchpt);
24016 ori4 = orient3dfast(pa, pc, pd, searchpt);
24017 if (fabs(ori1 / vol) < b->epsilon) ori1 = 0;
24018 if (fabs(ori2 / vol) < b->epsilon) ori2 = 0;
24019 if (fabs(ori3 / vol) < b->epsilon) ori3 = 0;
24020 if (fabs(ori4 / vol) < b->epsilon) ori4 = 0;
24023 tetrahedrons->traversalinit();
24024 searchtet->tet = tetrahedrontraverse();
24025 while (searchtet->tet != NULL) {
24026 pa = org(*searchtet);
24027 pb = dest(*searchtet);
24028 pc = apex(*searchtet);
24029 pd = oppo(*searchtet);
24031 vol = orient3dfast(pa, pb, pc, pd);
24033 ori1 = orient3dfast(pa, pb, pc, searchpt);
24034 if (fabs(ori1 / vol) < b->epsilon) ori1 = 0;
24036 ori2 = orient3dfast(pb, pa, pd, searchpt);
24037 if (fabs(ori2 / vol) < b->epsilon) ori2 = 0;
24039 ori3 = orient3dfast(pc, pb, pd, searchpt);
24040 if (fabs(ori3 / vol) < b->epsilon) ori3 = 0;
24042 ori4 = orient3dfast(pa, pc, pd, searchpt);
24043 if (fabs(ori4 / vol) < b->epsilon) ori4 = 0;
24053 searchtet->tet = tetrahedrontraverse();
24058 if (searchtet->tet != NULL) {
24063 enextself(*searchtet);
24075 eprevself(*searchtet);
24078 enextself(*searchtet);
24083 eprevself(*searchtet);
24092 esymself(*searchtet);
24094 eprevself(*searchtet);
24102 enextself(*searchtet);
24110 enextself(*searchtet);
24111 esymself(*searchtet);
24113 eprevself(*searchtet);
24120 eprevself(*searchtet);
24121 esymself(*searchtet);
24124 loc = INTETRAHEDRON;
24145 REAL tetgenmesh::getpointmeshsize(point searchpt, triface *searchtet,
int iloc)
24147 point *pts, pa, pb, pc;
24148 REAL volume, vol[4], wei[4];
24154 if (iloc == (
int) INTETRAHEDRON) {
24155 pts = (point *) &(searchtet->tet[4]);
24157 if ((pts[0][pointmtrindex] > 0) && (pts[1][pointmtrindex] > 0) &&
24158 (pts[2][pointmtrindex] > 0) && (pts[3][pointmtrindex] > 0)) {
24160 volume = orient3dfast(pts[0], pts[1], pts[2], pts[3]);
24161 vol[0] = orient3dfast(searchpt, pts[1], pts[2], pts[3]);
24162 vol[1] = orient3dfast(pts[0], searchpt, pts[2], pts[3]);
24163 vol[2] = orient3dfast(pts[0], pts[1], searchpt, pts[3]);
24164 vol[3] = orient3dfast(pts[0], pts[1], pts[2], searchpt);
24165 for (i = 0; i < 4; i++) {
24166 wei[i] = fabs(vol[i] / volume);
24167 size += (wei[i] * pts[i][pointmtrindex]);
24170 }
else if (iloc == (
int) ONFACE) {
24171 pa = org(*searchtet);
24172 pb = dest(*searchtet);
24173 pc = apex(*searchtet);
24174 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
24175 (pc[pointmtrindex] > 0)) {
24176 volume = triarea(pa, pb, pc);
24177 vol[0] = triarea(searchpt, pb, pc);
24178 vol[1] = triarea(pa, searchpt, pc);
24179 vol[2] = triarea(pa, pb, searchpt);
24180 size = (vol[0] / volume) * pa[pointmtrindex]
24181 + (vol[1] / volume) * pb[pointmtrindex]
24182 + (vol[2] / volume) * pc[pointmtrindex];
24184 }
else if (iloc == (
int) ONEDGE) {
24185 pa = org(*searchtet);
24186 pb = dest(*searchtet);
24187 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
24188 volume = distance(pa, pb);
24189 vol[0] = distance(searchpt, pb);
24190 vol[1] = distance(pa, searchpt);
24191 size = (vol[0] / volume) * pa[pointmtrindex]
24192 + (vol[1] / volume) * pb[pointmtrindex];
24194 }
else if (iloc == (
int) ONVERTEX) {
24195 pa = org(*searchtet);
24196 if (pa[pointmtrindex] > 0) {
24197 size = pa[pointmtrindex];
24211 void tetgenmesh::interpolatemeshsize()
24215 REAL minval = 0.0, maxval = 0.0;
24220 printf(
"Interpolating mesh size ...\n");
24223 long bak_nonregularcount = nonregularcount;
24224 nonregularcount = 0l;
24225 long baksmaples = bgm->samples;
24230 points->traversalinit();
24231 ploop = pointtraverse();
24232 while (ploop != NULL) {
24234 searchtet.tet = NULL;
24235 iloc = bgm->scoutpoint(ploop, &searchtet, 1);
24236 if (iloc != (
int) OUTSIDE) {
24238 ploop[pointmtrindex] = bgm->getpointmeshsize(ploop, &searchtet, iloc);
24239 setpoint2bgmtet(ploop, bgm->encode(searchtet));
24242 minval = maxval = ploop[pointmtrindex];
24244 if (ploop[pointmtrindex] < minval) {
24245 minval = ploop[pointmtrindex];
24247 if (ploop[pointmtrindex] > maxval) {
24248 maxval = ploop[pointmtrindex];
24254 printf(
"Warnning: Failed to locate point %d in source mesh.\n",
24258 ploop = pointtraverse();
24262 printf(
" Interoplated %d points.\n", count);
24263 if (nonregularcount > 0l) {
24264 printf(
" Performed %ld brute-force searches.\n", nonregularcount);
24266 printf(
" Size rangle [%.17g, %.17g].\n", minval, maxval);
24269 bgm->samples = baksmaples;
24270 nonregularcount = bak_nonregularcount;
24282 void tetgenmesh::insertconstrainedpoints(point *insertarray,
int arylen,
24285 triface searchtet, spintet;
24288 insertvertexflags ivf;
24289 flipconstraints fc;
24295 printf(
" Inserting %d constrained points\n", arylen);
24300 printf(
" Using the input order.\n");
24304 printf(
" Permuting vertices.\n");
24309 for (i = 0; i < arylen; i++) {
24310 randindex = rand() % (i + 1);
24311 swappoint = insertarray[i];
24312 insertarray[i] = insertarray[randindex];
24313 insertarray[randindex] = swappoint;
24315 if (b->brio_hilbert) {
24317 printf(
" Sorting vertices.\n");
24319 hilbert_init(in->mesh_dim);
24321 brio_multiscale_sort(insertarray, arylen, b->brio_threshold,
24322 b->brio_ratio, &ngroup);
24328 long bak_nonregularcount = nonregularcount;
24329 nonregularcount = 0l;
24330 long baksmaples = samples;
24333 long bak_seg_count = st_segref_count;
24334 long bak_fac_count = st_facref_count;
24335 long bak_vol_count = st_volref_count;
24350 ivf.rejflag = rejflag;
24351 ivf.chkencflag = 0;
24352 ivf.sloc = (int) INSTAR;
24354 ivf.splitbdflag = 1;
24355 ivf.respectbdflag = 1;
24356 ivf.assignmeshsize = b->metric;
24358 encseglist =
new arraypool(
sizeof(face), 8);
24359 encshlist =
new arraypool(
sizeof(badface), 8);
24362 for (i = 0; i < arylen; i++) {
24365 searchtet.tet = NULL;
24366 ivf.iloc = scoutpoint(insertarray[i], &searchtet, randflag);
24369 setpointtype(insertarray[i], FREEVOLVERTEX);
24371 splitseg.sh = NULL;
24372 if (ivf.iloc == (
int) ONEDGE) {
24373 if (issubseg(searchtet)) {
24374 tsspivot1(searchtet, splitseg);
24375 setpointtype(insertarray[i], FREESEGVERTEX);
24379 spintet = searchtet;
24381 if (issubface(spintet)) {
24382 tspivot(spintet, splitsh);
24383 setpointtype(insertarray[i], FREEFACETVERTEX);
24387 fnextself(spintet);
24388 if (spintet.tet == searchtet.tet)
break;
24391 }
else if (ivf.iloc == (
int) ONFACE) {
24392 if (issubface(searchtet)) {
24393 tspivot(searchtet, splitsh);
24394 setpointtype(insertarray[i], FREEFACETVERTEX);
24400 if (insertpoint(insertarray[i], &searchtet, &splitsh, &splitseg, &ivf)) {
24401 if (flipstack != NULL) {
24405 unflipqueue->restart();
24408 if (pointtype(insertarray[i]) == FREESEGVERTEX) {
24410 }
else if (pointtype(insertarray[i]) == FREEFACETVERTEX) {
24418 setpointtype(insertarray[i], UNUSEDVERTEX);
24420 encseglist->restart();
24421 encshlist->restart();
24429 printf(
" Inserted %ld (%ld, %ld, %ld) vertices.\n",
24430 st_segref_count + st_facref_count + st_volref_count -
24431 (bak_seg_count + bak_fac_count + bak_vol_count),
24432 st_segref_count - bak_seg_count, st_facref_count - bak_fac_count,
24433 st_volref_count - bak_vol_count);
24434 if (nonregularcount > 0l) {
24435 printf(
" Performed %ld brute-force searches.\n", nonregularcount);
24439 nonregularcount = bak_nonregularcount;
24440 samples = baksmaples;
24443 void tetgenmesh::insertconstrainedpoints(
tetgenio *addio)
24445 point *insertarray, newpt;
24447 int index, attribindex, mtrindex;
24451 printf(
"Inserting constrained points ...\n");
24454 insertarray =
new point[addio->numberofpoints];
24460 for (i = 0; i < addio->numberofpoints; i++) {
24461 x = addio->pointlist[index++];
24462 y = addio->pointlist[index++];
24463 z = addio->pointlist[index++];
24465 if ((x < xmin) || (x > xmax) || (y < ymin) || (y > ymax) ||
24466 (z < zmin) || (z > zmax)) {
24468 printf(
"Warning: Point #%d lies outside the bounding box. Ignored\n",
24469 i + in->firstnumber);
24473 makepoint(&newpt, UNUSEDVERTEX);
24478 for (j = 0; j < addio->numberofpointattributes; j++) {
24479 newpt[3 + j] = addio->pointattributelist[attribindex++];
24482 for (j = 0; j < addio->numberofpointmtrs; j++) {
24483 newpt[pointmtrindex + j] = addio->pointmtrlist[mtrindex++];
24486 if (addio->numberofpointattributes > 0) {
24493 if (w < fabs(y)) w = fabs(y);
24494 if (w < fabs(z)) w = fabs(z);
24496 if (b->weighted_param == 0) {
24497 newpt[3] = x * x + y * y + z * z - w;
24502 insertarray[arylen] = newpt;
24512 insertconstrainedpoints(insertarray, arylen, rejflag);
24514 delete [] insertarray;
24523 void tetgenmesh::collectremovepoints(arraypool *remptlist)
24525 point ptloop, *parypt;
24533 points->traversalinit();
24534 ptloop = pointtraverse();
24535 while (ptloop != NULL) {
24537 vt = pointtype(ptloop);
24538 if ((vt == RIDGEVERTEX) || (vt == ACUTEVERTEX) || (vt == FACETVERTEX) ||
24539 (vt == FREEFACETVERTEX) || (vt == FREESEGVERTEX) || (vt == UNUSEDVERTEX)) {
24540 ptloop = pointtraverse();
24543 if (ptloop[pointmtrindex] > 0) {
24545 getvertexstar(1, ptloop, cavetetlist, cavetetvertlist, NULL);
24546 parypt = (point *) fastlookup(cavetetvertlist, 0);
24547 smlen = distance(ptloop, *parypt);
24548 for (i = 1; i < cavetetvertlist->objects; i++) {
24549 parypt = (point *) fastlookup(cavetetvertlist, i);
24550 len = distance(ptloop, *parypt);
24555 cavetetvertlist->restart();
24556 cavetetlist->restart();
24557 if (smlen < ptloop[pointmtrindex]) {
24559 remptlist->newindex((
void **) &parypt);
24563 ptloop = pointtraverse();
24565 if (b->verbose > 1) {
24566 printf(
" Coarsen %ld oversized points.\n", remptlist->objects);
24571 if (in->pointmarkerlist != NULL) {
24572 long bak_count = remptlist->objects;
24573 points->traversalinit();
24574 ptloop = pointtraverse();
24576 while (ptloop != NULL) {
24577 if (index < in->numberofpoints) {
24578 if (in->pointmarkerlist[index] == -1) {
24580 remptlist->newindex((
void **) &parypt);
24588 ptloop = pointtraverse();
24590 if (b->verbose > 1) {
24591 printf(
" Coarsen %ld marked points.\n", remptlist->objects - bak_count);
24595 if (b->coarsen_param > 0) {
24597 if (b->verbose > 1) {
24598 printf(
" Coarsen %g percent of interior points.\n",
24599 b->coarsen_percent * 100.0);
24601 arraypool *intptlist =
new arraypool(
sizeof(point *), 10);
24603 points->traversalinit();
24604 ptloop = pointtraverse();
24605 while (ptloop != NULL) {
24606 vt = pointtype(ptloop);
24607 if ((vt == VOLVERTEX) || (vt == FREEVOLVERTEX) ||
24608 (vt == FREEFACETVERTEX) || (vt == FREESEGVERTEX)) {
24609 intptlist->newindex((
void **) &parypt);
24612 ptloop = pointtraverse();
24614 if (intptlist->objects > 0l) {
24616 point *parypt_i, swappt;
24618 srand(intptlist->objects);
24619 for (i = 0; i < intptlist->objects; i++) {
24620 randindex = rand() % (i + 1);
24621 parypt_i = (point *) fastlookup(intptlist, i);
24622 parypt = (point *) fastlookup(intptlist, randindex);
24624 swappt = *parypt_i;
24625 *parypt_i = *parypt;
24628 int remcount = (int) ((REAL) intptlist->objects * b->coarsen_percent);
24630 for (i = 0; i < remcount; i++) {
24631 parypt_i = (point *) fastlookup(intptlist, i);
24632 if (!pinfected(*parypt_i)) {
24633 pinfected(*parypt_i);
24634 remptlist->newindex((
void **) &parypt);
24635 *parypt = *parypt_i;
24643 for (
int i = 0; i < remptlist->objects; i++) {
24644 parypt = (point *) fastlookup(remptlist, i);
24645 puninfect(*parypt);
24649 void tetgenmesh::meshcoarsening()
24651 arraypool *remptlist;
24654 printf(
"Mesh coarsening ...\n");
24658 remptlist =
new arraypool(
sizeof(point *), 10);
24659 collectremovepoints(remptlist);
24661 if (remptlist->objects == 0l) {
24667 if (remptlist->objects > 0l) {
24668 printf(
" Removing %ld points...\n", remptlist->objects);
24672 point *parypt, *plastpt;
24673 long ms = remptlist->objects;
24675 int bak_fliplinklevel = b->fliplinklevel;
24676 b->fliplinklevel = -1;
24677 autofliplinklevel = 1;
24682 if (b->verbose > 1) {
24683 printf(
" Removing points [%s level = %2d] #: %ld.\n",
24684 (b->fliplinklevel > 0) ?
"fixed" :
"auto",
24685 (b->fliplinklevel > 0) ? b->fliplinklevel : autofliplinklevel,
24686 remptlist->objects);
24690 for (i = 0; i < remptlist->objects; i++) {
24691 parypt = (point *) fastlookup(remptlist, i);
24692 if (removevertexbyflips(*parypt)) {
24694 plastpt = (point *) fastlookup(remptlist, remptlist->objects - 1);
24695 *parypt = *plastpt;
24696 remptlist->objects--;
24701 if (remptlist->objects > 0l) {
24702 if (b->fliplinklevel >= 0) {
24705 if (remptlist->objects == ms) {
24709 b->fliplinklevel = 100000;
24712 ms = remptlist->objects;
24717 autofliplinklevel+=b->fliplinklevelinc;
24724 if (remptlist->objects > 0l) {
24726 printf(
" %ld points are not removed !\n", remptlist->objects);
24730 b->fliplinklevel = bak_fliplinklevel;
24751 void tetgenmesh::makefacetverticesmap()
24753 arraypool *facetvertexlist, *vertlist, **paryvertlist;
24754 face subloop, neighsh, *parysh, *parysh1;
24755 point pa, *ppt, *parypt;
24757 int facetindex, totalvertices;
24761 printf(
" Creating the facet vertices map.\n");
24764 facetvertexlist =
new arraypool(
sizeof(arraypool *), 10);
24765 facetindex = totalvertices = 0;
24767 subfaces->traversalinit();
24768 subloop.sh = shellfacetraverse(subfaces);
24769 while (subloop.sh != NULL) {
24770 if (!sinfected(subloop)) {
24772 vertlist =
new arraypool(
sizeof(point *), 8);
24773 ppt = (point *) &(subloop.sh[3]);
24774 for (k = 0; k < 3; k++) {
24775 vt = pointtype(ppt[k]);
24776 if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) {
24778 vertlist->newindex((
void **) &parypt);
24783 caveshlist->newindex((
void **) &parysh);
24785 for (i = 0; i < caveshlist->objects; i++) {
24786 parysh = (face *) fastlookup(caveshlist, i);
24787 setfacetindex(*parysh, facetindex);
24788 for (j = 0; j < 3; j++) {
24789 if (!isshsubseg(*parysh)) {
24790 spivot(*parysh, neighsh);
24791 if (!sinfected(neighsh)) {
24792 pa = sapex(neighsh);
24793 if (!pinfected(pa)) {
24794 vt = pointtype(pa);
24795 if ((vt != FREESEGVERTEX) && (vt != FREEFACETVERTEX)) {
24797 vertlist->newindex((
void **) &parypt);
24802 caveshlist->newindex((
void **) &parysh1);
24803 *parysh1 = neighsh;
24806 senextself(*parysh);
24809 totalvertices += (int) vertlist->objects;
24811 for (k = 0; k < vertlist->objects; k++) {
24812 parypt = (point *) fastlookup(vertlist, k);
24813 puninfect(*parypt);
24815 caveshlist->restart();
24817 facetvertexlist->newindex((
void **) &paryvertlist);
24818 *paryvertlist = vertlist;
24821 subloop.sh = shellfacetraverse(subfaces);
24825 subfaces->traversalinit();
24826 subloop.sh = shellfacetraverse(subfaces);
24827 while (subloop.sh != NULL) {
24828 suninfect(subloop);
24829 subloop.sh = shellfacetraverse(subfaces);
24833 printf(
" Found %ld facets.\n", facetvertexlist->objects);
24836 idx2facetlist =
new int[facetindex + 1];
24837 facetverticeslist =
new point[totalvertices];
24839 totalworkmemory += ((facetindex + 1) *
sizeof(
int) +
24840 totalvertices *
sizeof(point *));
24842 idx2facetlist[0] = 0;
24843 for (i = 0, k = 0; i < facetindex; i++) {
24844 paryvertlist = (arraypool **) fastlookup(facetvertexlist, i);
24845 vertlist = *paryvertlist;
24846 idx2facetlist[i + 1] = (idx2facetlist[i] + (int) vertlist->objects);
24847 for (j = 0; j < vertlist->objects; j++) {
24848 parypt = (point *) fastlookup(vertlist, j);
24849 facetverticeslist[k] = *parypt;
24855 for (i = 0; i < facetvertexlist->objects; i++) {
24856 paryvertlist = (arraypool **) fastlookup(facetvertexlist, i);
24857 vertlist = *paryvertlist;
24860 delete facetvertexlist;
24870 int tetgenmesh::segsegadjacent(face *seg1, face *seg2)
24872 int segidx1 = getfacetindex(*seg1);
24873 int segidx2 = getfacetindex(*seg2);
24875 if (segidx1 == segidx2)
return 0;
24877 point pa1 = segmentendpointslist[segidx1 * 2];
24878 point pb1 = segmentendpointslist[segidx1 * 2 + 1];
24879 point pa2 = segmentendpointslist[segidx2 * 2];
24880 point pb2 = segmentendpointslist[segidx2 * 2 + 1];
24882 if ((pa1 == pa2) || (pa1 == pb2) || (pb1 == pa2) || (pb1 == pb2)) {
24888 int tetgenmesh::segfacetadjacent(face *subseg, face *subsh)
24890 int segidx = getfacetindex(*subseg);
24891 point pa = segmentendpointslist[segidx * 2];
24892 point pb = segmentendpointslist[segidx * 2 + 1];
24897 int fidx = getfacetindex(*subsh);
24900 for (i = idx2facetlist[fidx]; i < idx2facetlist[fidx+1]; i++) {
24901 if (pinfected(facetverticeslist[i])) count++;
24910 int tetgenmesh::facetfacetadjacent(face *subsh1, face *subsh2)
24914 int fidx1 = getfacetindex(*subsh1);
24915 int fidx2 = getfacetindex(*subsh2);
24917 if (fidx1 == fidx2)
return 0;
24919 for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) {
24920 pinfect(facetverticeslist[i]);
24923 for (i = idx2facetlist[fidx2]; i < idx2facetlist[fidx2+1]; i++) {
24924 if (pinfected(facetverticeslist[i])) count++;
24928 for (i = idx2facetlist[fidx1]; i < idx2facetlist[fidx1+1]; i++) {
24929 puninfect(facetverticeslist[i]);
24945 void tetgenmesh::save_segmentpoint_insradius(point segpt,point parentpt,REAL r)
24948 if (pointtype(parentpt) == FREESEGVERTEX) {
24949 face parentseg1, parentseg2;
24950 sdecode(point2sh(segpt), parentseg1);
24951 sdecode(point2sh(parentpt), parentseg2);
24952 if (segsegadjacent(&parentseg1, &parentseg2)) {
24953 rp = getpointinsradius(parentpt);
24959 }
else if (pointtype(parentpt) == FREEFACETVERTEX) {
24960 face parentseg, parentsh;
24961 sdecode(point2sh(segpt), parentseg);
24962 sdecode(point2sh(parentpt), parentsh);
24963 if (segfacetadjacent(&parentseg, &parentsh)) {
24964 rp = getpointinsradius(parentpt);
24965 if ((sqrt(2.0) * rv) < rp) {
24967 rv = rp / sqrt(2.0);
24971 setpointinsradius(segpt, rv);
24974 void tetgenmesh::save_facetpoint_insradius(point facpt,point parentpt,REAL r)
24977 if (pointtype(parentpt) == FREESEGVERTEX) {
24978 face parentseg, parentsh;
24979 sdecode(point2sh(parentpt), parentseg);
24980 sdecode(point2sh(facpt), parentsh);
24981 if (segfacetadjacent(&parentseg, &parentsh)) {
24982 rp = getpointinsradius(parentpt);
24983 if (rv < (sqrt(2.0) * rp)) {
24984 rv = sqrt(2.0) * rp;
24987 }
else if (pointtype(parentpt) == FREEFACETVERTEX) {
24988 face parentsh1, parentsh2;
24989 sdecode(point2sh(parentpt), parentsh1);
24990 sdecode(point2sh(facpt), parentsh2);
24991 if (facetfacetadjacent(&parentsh1, &parentsh2)) {
24992 rp = getpointinsradius(parentpt);
24998 setpointinsradius(facpt, rv);
25007 void tetgenmesh::enqueuesubface(memorypool *pool, face *chkface)
25009 if (!smarktest2ed(*chkface)) {
25010 smarktest2(*chkface);
25011 face *queface = (face *) pool->alloc();
25012 *queface = *chkface;
25022 void tetgenmesh::enqueuetetrahedron(triface *chktet)
25024 if (!marktest2ed(*chktet)) {
25025 marktest2(*chktet);
25026 triface *quetet = (triface *) badtetrahedrons->alloc();
25037 int tetgenmesh::checkseg4encroach(point pa, point pb, point checkpt)
25042 v1[0] = pa[0] - checkpt[0];
25043 v1[1] = pa[1] - checkpt[1];
25044 v1[2] = pa[2] - checkpt[2];
25045 v2[0] = pb[0] - checkpt[0];
25046 v2[1] = pb[1] - checkpt[1];
25047 v2[2] = pb[2] - checkpt[2];
25049 if (dot(v1, v2) < 0) {
25052 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0)) {
25054 REAL prjpt[3], u, v, t;
25055 projpt2edge(checkpt, pa, pb, prjpt);
25057 u = distance(pa, pb);
25058 v = distance(pa, prjpt);
25061 u = pa[pointmtrindex] + t * (pb[pointmtrindex] - pa[pointmtrindex]);
25062 v = distance(checkpt, prjpt);
25092 int tetgenmesh::checkseg4split(face *chkseg, point& encpt,
int& qflag)
25094 REAL ccent[3], len, r;
25097 point forg = sorg(*chkseg);
25098 point fdest = sdest(*chkseg);
25104 len = distance(forg, fdest);
25106 for (i = 0; i < 3; i++) {
25107 ccent[i] = 0.5 * (forg[i] + fdest[i]);
25111 if (checkconstraints && (areabound(*chkseg) > 0.0)) {
25112 if (len > areabound(*chkseg)) {
25118 if (b->fixedvolume) {
25119 if ((len * len * len) > b->maxvolume) {
25127 if (((forg[pointmtrindex] > 0) && (r > forg[pointmtrindex])) ||
25128 ((fdest[pointmtrindex]) > 0 && (r > fdest[pointmtrindex]))) {
25138 triface searchtet, spintet;
25140 REAL d, diff, smdist = 0;
25143 sstpivot1(*chkseg, searchtet);
25144 spintet = searchtet;
25146 eapex = apex(spintet);
25147 if (eapex != dummypoint) {
25148 d = distance(ccent, eapex);
25150 if (fabs(diff) / r < b->epsilon) diff = 0.0;
25153 if (useinsertradius) {
25154 if (encpt == NULL) {
25170 fnextself(spintet);
25171 if (spintet.tet == searchtet.tet)
break;
25174 if (encpt != NULL) {
25192 #pragma GCC diagnostic push 25193 #pragma GCC diagnostic ignored "-Wunused-parameter" 25194 int tetgenmesh::splitsegment(face *splitseg, point encpt, REAL rrp,
25195 point encpt1, point encpt2,
int qflag,
25199 if (!qflag && smarktest3ed(*splitseg)) {
25206 if (checkconstraints) {
25208 if (areabound(*splitseg) == 0) {
25211 face parentsh, spinsh;
25213 spivot(*splitseg, parentsh);
25214 if (parentsh.sh == NULL) {
25219 if (areabound(spinsh) == 0)
break;
25220 spivotself(spinsh);
25221 if (spinsh.sh == parentsh.sh)
break;
25222 if (spinsh.sh == NULL)
break;
25224 if ((!spinsh.sh) || (areabound(spinsh) == 0)) {
25237 insertvertexflags ivf;
25239 makepoint(&newpt, FREESEGVERTEX);
25240 getsteinerptonsegment(splitseg, encpt, newpt);
25242 if (!qflag && !b->cdtrefine) {
25245 spivot(*splitseg, parentsh);
25246 if (parentsh.sh != NULL) {
25247 face spinsh, neighsh;
25251 for (
int i = 0; i < 2; i++) {
25253 senext(spinsh, neighsh);
25255 senext2(spinsh, neighsh);
25257 if (isshsubseg(neighsh)) {
25258 sspivot(neighsh, neighseg);
25259 if (checkseg4encroach(sorg(neighseg), sdest(neighseg), newpt)) {
25260 pointdealloc(newpt);
25265 spivotself(spinsh);
25266 if (spinsh.sh == NULL)
break;
25267 if (spinsh.sh == parentsh.sh)
break;
25273 sstpivot1(*splitseg, searchtet);
25274 ivf.iloc = (int) ONEDGE;
25282 ivf.chkencflag = chkencflag;
25283 ivf.sloc = (int) INSTAR;
25285 ivf.splitbdflag = 1;
25286 ivf.respectbdflag = 1;
25287 ivf.assignmeshsize = b->metric;
25288 ivf.smlenflag = useinsertradius;
25291 if (insertpoint(newpt, &searchtet, &searchsh, splitseg, &ivf)) {
25293 if (steinerleft > 0) steinerleft--;
25294 if (useinsertradius) {
25295 save_segmentpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
25297 if (flipstack != NULL) {
25298 flipconstraints fc;
25299 fc.chkencflag = chkencflag;
25302 unflipqueue->restart();
25307 if (ivf.iloc == (
int) NEARVERTEX) {
25308 terminatetetgen(
this, 2);
25310 pointdealloc(newpt);
25312 smarktest3(*splitseg);
25316 #pragma GCC diagnostic pop 25323 void tetgenmesh::repairencsegs(
int chkencflag)
25326 point encpt = NULL;
25331 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
25332 badsubsegs->traversalinit();
25333 bface = (face *) badsubsegs->traverse();
25334 while ((bface != NULL) && (steinerleft != 0)) {
25336 if (bface->shver >= 0) {
25338 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25340 if (smarktest2ed(*bface)) {
25341 sunmarktest2(*bface);
25342 if (checkseg4split(bface, encpt, qflag)) {
25343 splitsegment(bface, encpt, 0, NULL, NULL, qflag, chkencflag);
25349 badsubsegs->dealloc((
void *) bface);
25351 bface = (face *) badsubsegs->traverse();
25355 if (badsubsegs->items > 0) {
25357 printf(
"The desired number of Steiner points is reached.\n");
25359 badsubsegs->traversalinit();
25360 bface = (face *) badsubsegs->traverse();
25361 while (bface != NULL) {
25363 if (bface->shver >= 0) {
25364 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25365 if (smarktest2ed(*bface)) {
25366 sunmarktest2(*bface);
25370 bface = (face *) badsubsegs->traverse();
25372 badsubsegs->restart();
25382 int tetgenmesh::checkfac4encroach(point pa, point pb, point pc, point checkpt,
25383 REAL* cent, REAL* r)
25386 int encroached = 0;
25388 circumsphere(pa, pb, pc, NULL, cent, &rd);
25390 terminatetetgen(
this, 2);
25393 if (b->use_equatorial_lens) {
25394 REAL normal[3], fcenter[3];
25395 REAL xta, yta, zta;
25398 fcenter[0] = cent[0] - pc[0];
25399 fcenter[1] = cent[1] - pc[1];
25400 fcenter[2] = cent[2] - pc[2];
25403 facenormal(pa, pb, pc, normal, 1, NULL);
25404 multiplier = 0.985 * sqrt((fcenter[0]*fcenter[0] + fcenter[1]*fcenter[1] +
25405 fcenter[2]*fcenter[2]) /
25406 (3.0 * (normal[0] * normal[0] + normal[1] * normal[1] +
25407 normal[2] * normal[2])));
25408 xta = checkpt[0] - pc[0];
25409 yta = checkpt[1] - pc[1];
25410 zta = checkpt[2] - pc[2];
25412 if ((xta * normal[0] + yta * normal[1] + zta * normal[2]) < 0) {
25414 normal[0] = -normal[0];
25415 normal[1] = -normal[1];
25416 normal[2] = -normal[2];
25419 if (xta * xta + yta * yta + zta * zta <=
25420 2.0 * (xta * (fcenter[0] - multiplier * normal[0]) +
25421 yta * (fcenter[1] - multiplier * normal[1]) +
25422 zta * (fcenter[2] - multiplier * normal[2]))) {
25426 len = distance(cent, checkpt);
25427 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
25436 if ((pa[pointmtrindex] > 0) && (pb[pointmtrindex] > 0) &&
25437 (pc[pointmtrindex] > 0)) {
25439 REAL prjpt[3], n[3];
25440 REAL a, a1, a2, a3;
25441 projpt2face(checkpt, pa, pb, pc, prjpt);
25443 facenormal(pa, pb, pc, n, 1, NULL);
25444 a = sqrt(dot(n,n));
25446 facenormal(pa, pb, prjpt, n, 1, NULL);
25447 a1 = sqrt(dot(n,n));
25448 facenormal(pb, pc, prjpt, n, 1, NULL);
25449 a2 = sqrt(dot(n,n));
25450 facenormal(pc, pa, prjpt, n, 1, NULL);
25451 a3 = sqrt(dot(n,n));
25452 if ((fabs(a1 + a2 + a3 - a) / a) < b->epsilon) {
25455 rd = a1 / a * pc[pointmtrindex]
25456 + a2 / a * pa[pointmtrindex]
25457 + a3 / a * pb[pointmtrindex];
25458 len = distance(prjpt, checkpt);
25489 int tetgenmesh::checkfac4split(face *chkfac, point& encpt,
int& qflag,
25493 REAL area, rd, len;
25494 REAL A[4][4], rhs[4], D;
25501 pa = sorg(*chkfac);
25502 pb = sdest(*chkfac);
25503 pc = sapex(*chkfac);
25506 A[0][0] = pb[0] - pa[0];
25507 A[0][1] = pb[1] - pa[1];
25508 A[0][2] = pb[2] - pa[2];
25509 A[1][0] = pc[0] - pa[0];
25510 A[1][1] = pc[1] - pa[1];
25511 A[1][2] = pc[2] - pa[2];
25512 cross(A[0], A[1], A[2]);
25514 area = 0.5 * sqrt(dot(A[2], A[2]));
25517 rhs[0] = 0.5 * dot(A[0], A[0]);
25518 rhs[1] = 0.5 * dot(A[1], A[1]);
25523 if (!lu_decmp(A, 3, indx, &D, 0)) {
25525 terminatetetgen(
this, 2);
25528 lu_solve(A, 3, indx, rhs, 0);
25529 cent[0] = pa[0] + rhs[0];
25530 cent[1] = pa[1] + rhs[1];
25531 cent[2] = pa[2] + rhs[2];
25532 rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
25534 if (checkconstraints && (areabound(*chkfac) > 0.0)) {
25536 if (area > areabound(*chkfac)) {
25542 if (b->fixedvolume) {
25543 if ((area * sqrt(area)) > b->maxvolume) {
25549 if (b->varvolume) {
25554 stpivot(*chkfac, adjtet);
25555 if (!ishulltet(adjtet)) {
25556 volbnd = volumebound(adjtet.tet);
25557 if ((volbnd > 0) && (area * sqrt(area)) > volbnd) {
25563 if (!ishulltet(adjtet)) {
25564 volbnd = volumebound(adjtet.tet);
25565 if ((volbnd > 0) && (area * sqrt(area)) > volbnd) {
25574 if (((pa[pointmtrindex] > 0) && (rd > pa[pointmtrindex])) ||
25575 ((pb[pointmtrindex] > 0) && (rd > pb[pointmtrindex])) ||
25576 ((pc[pointmtrindex] > 0) && (rd > pc[pointmtrindex]))) {
25586 for (i = 0; i < 2; i++) {
25587 stpivot(*chkfac, searchtet);
25588 if (!ishulltet(searchtet)) {
25589 int encroached = 0;
25591 len = distance(oppo(searchtet), cent);
25592 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
25594 if (b->use_equatorial_lens) {
25595 point tettapex = oppo(searchtet);
25596 REAL normal[3], fcenter[3];
25597 REAL xta, yta, zta;
25600 point fa = org(searchtet);
25601 point fb = dest(searchtet);
25602 point fc = apex(searchtet);
25604 fcenter[0] = cent[0] - fc[0];
25605 fcenter[1] = cent[1] - fc[1];
25606 fcenter[2] = cent[2] - fc[2];
25608 facenormal(fa, fb, fc, normal, 1, NULL);
25609 multiplier = 0.985 * sqrt((fcenter[0]*fcenter[0] + fcenter[1]*fcenter[1] +
25610 fcenter[2]*fcenter[2]) /
25611 (3.0 * (normal[0] * normal[0] + normal[1] * normal[1] +
25612 normal[2] * normal[2])));
25613 xta = tettapex[0] - fc[0];
25614 yta = tettapex[1] - fc[1];
25615 zta = tettapex[2] - fc[2];
25616 if (xta * xta + yta * yta + zta * zta <=
25617 2.0 * (xta * (fcenter[0] - multiplier * normal[0]) +
25618 yta * (fcenter[1] - multiplier * normal[1]) +
25619 zta * (fcenter[2] - multiplier * normal[2]))) {
25631 encpt = oppo(searchtet);
25635 encpt = oppo(searchtet);
25641 sesymself(*chkfac);
25644 return encpt != NULL;
25667 int tetgenmesh::splitsubface(face *splitfac, point encpt, point encpt1,
25668 int qflag, REAL *ccent,
int chkencflag)
25671 if (!qflag && smarktest3ed(*splitfac)) {
25677 if (checkconstraints) {
25680 if (areabound(*splitfac) == 0) {
25688 if (useinsertradius) {
25689 if (encpt != NULL) {
25691 REAL rv = distance(encpt, ccent);
25692 if (pointtype(encpt) == FREESEGVERTEX) {
25694 sdecode(point2sh(encpt), parentseg);
25695 if (segfacetadjacent(&parentseg, splitfac)) {
25696 rp = getpointinsradius(encpt);
25697 if (rv < (sqrt(2.0) * rp)) {
25702 }
else if (pointtype(encpt) == FREEFACETVERTEX) {
25704 sdecode(point2sh(encpt), parentsh);
25705 if (facetfacetadjacent(&parentsh, splitfac)) {
25706 rp = getpointinsradius(encpt);
25716 insertvertexflags ivf;
25721 makepoint(&newpt, FREEFACETVERTEX);
25723 for (i = 0; i < 3; i++) newpt[i] = ccent[i];
25726 searchsh = *splitfac;
25730 calculateabovepoint4(newpt, sorg(*splitfac), sdest(*splitfac),
25735 ivf.iloc = (int) slocate(newpt, &searchsh, 1, 0, 0);
25737 if (!((ivf.iloc == (
int) ONFACE) || (ivf.iloc == (
int) ONEDGE))) {
25739 pointdealloc(newpt);
25741 smarktest3(*splitfac);
25749 stpivot(searchsh, searchtet);
25756 ivf.chkencflag = chkencflag;
25757 ivf.sloc = (int) INSTAR;
25759 ivf.splitbdflag = 1;
25761 ivf.respectbdflag = 1;
25762 ivf.assignmeshsize = b->metric;
25763 ivf.refineflag = 2;
25764 ivf.refinesh = *splitfac;
25765 ivf.smlenflag = useinsertradius;
25768 if (insertpoint(newpt, &searchtet, &searchsh, NULL, &ivf)) {
25770 if (steinerleft > 0) steinerleft--;
25771 if (useinsertradius) {
25772 save_facetpoint_insradius(newpt, ivf.parentpt, ivf.smlen);
25774 if (flipstack != NULL) {
25775 flipconstraints fc;
25776 fc.chkencflag = chkencflag;
25779 unflipqueue->restart();
25784 pointdealloc(newpt);
25785 if (ivf.iloc == (
int) ENCSEGMENT) {
25789 for (i = 0; i < encseglist->objects; i++) {
25790 paryseg = (face *) fastlookup(encseglist, i);
25791 if (splitsegment(paryseg, NULL, 0.0, encpt, encpt1, qflag,
25797 encseglist->restart();
25800 if (badsubsegs->items > 0) {
25801 repairencsegs(chkencflag | 1);
25806 if (ivf.iloc == (
int) NEARVERTEX) {
25807 terminatetetgen(
this, 2);
25811 smarktest3(*splitfac);
25822 void tetgenmesh::repairencfacs(
int chkencflag)
25825 point encpt = NULL;
25831 while ((badsubfacs->items > 0) && (steinerleft != 0)) {
25832 badsubfacs->traversalinit();
25833 bface = (face *) badsubfacs->traverse();
25834 while ((bface != NULL) && (steinerleft != 0)) {
25836 if (bface->shver >= 0) {
25838 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25840 if (smarktest2ed(*bface)) {
25841 sunmarktest2(*bface);
25842 if (checkfac4split(bface, encpt, qflag, ccent)) {
25843 splitsubface(bface, encpt, NULL, qflag, ccent, chkencflag);
25848 badsubfacs->dealloc((
void *) bface);
25850 bface = (face *) badsubfacs->traverse();
25854 if (badsubfacs->items > 0) {
25855 if (steinerleft == 0) {
25857 printf(
"The desired number of Steiner points is reached.\n");
25860 terminatetetgen(
this, 2);
25862 badsubfacs->traversalinit();
25863 bface = (face *) badsubfacs->traverse();
25864 while (bface != NULL) {
25866 if (bface->shver >= 0) {
25867 if ((bface->sh != NULL) && (bface->sh[3] != NULL)) {
25868 if (smarktest2ed(*bface)) {
25869 sunmarktest2(*bface);
25873 bface = (face *) badsubfacs->traverse();
25875 badsubfacs->restart();
25885 int tetgenmesh::checktet4split(triface *chktet,
int &qflag, REAL *ccent)
25887 point pa, pb, pc, pd, *ppt;
25888 REAL vda[3], vdb[3], vdc[3];
25889 REAL vab[3], vbc[3], vca[3];
25890 REAL N[4][3], L[4], cosd[6], elen[6];
25891 REAL maxcosd, vol, volbnd, smlen = 0, rd;
25892 REAL A[4][4], rhs[4], D;
25898 if (elemattribute(chktet->tet, numelemattrib - 1) == -1.0) {
25905 pd = (point) chktet->tet[7];
25906 if (pd == dummypoint) {
25910 pa = (point) chktet->tet[4];
25911 pb = (point) chktet->tet[5];
25912 pc = (point) chktet->tet[6];
25916 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
25917 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
25918 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
25921 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
25922 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
25923 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
25925 if (!lu_decmp(A, 3, indx, &D, 0)) {
25933 if (b->varvolume || b->fixedvolume) {
25934 vol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
25935 if (b->fixedvolume) {
25936 if (vol > b->maxvolume) {
25940 if (!qflag && b->varvolume) {
25941 volbnd = volumebound(chktet->tet);
25942 if ((volbnd > 0.0) && (vol > volbnd)) {
25948 rhs[0] = 0.5 * dot(vda, vda);
25949 rhs[1] = 0.5 * dot(vdb, vdb);
25950 rhs[2] = 0.5 * dot(vdc, vdc);
25951 lu_solve(A, 3, indx, rhs, 0);
25952 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25959 rhs[0] = 0.5 * dot(vda, vda);
25960 rhs[1] = 0.5 * dot(vdb, vdb);
25961 rhs[2] = 0.5 * dot(vdc, vdc);
25962 lu_solve(A, 3, indx, rhs, 0);
25963 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25964 rd = sqrt(dot(rhs, rhs));
25966 ppt = (point *) &(chktet->tet[4]);
25967 for (i = 0; i < 4; i++) {
25968 if (ppt[i][pointmtrindex] > 0) {
25969 if (rd > ppt[i][pointmtrindex]) {
25977 if (in->tetunsuitable != NULL) {
25979 if ((*(in->tetunsuitable))(pa, pb, pc, pd, NULL, 0)) {
25981 rhs[0] = 0.5 * dot(vda, vda);
25982 rhs[1] = 0.5 * dot(vdb, vdb);
25983 rhs[2] = 0.5 * dot(vdc, vdc);
25984 lu_solve(A, 3, indx, rhs, 0);
25985 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
25990 if (useinsertradius) {
25998 checkedge.tet = chktet->tet;
25999 for (i = 0; i < 6; i++) {
26000 checkedge.ver = edge2ver[i];
26001 e1 = org(checkedge);
26002 e2 = dest(checkedge);
26003 elen[i] = distance(e1, e2);
26008 if (elen[i] < smlen) {
26015 checkedge.ver = edge2ver[j];
26018 e1 = org(checkedge);
26019 smrrv = getpointinsradius(e1);
26020 e2 = dest(checkedge);
26021 rrv = getpointinsradius(e2);
26033 if ((fabs(smrrv - smlen) / smlen) < b->epsilon) {
26036 if (smrrv > smlen) {
26043 if (b->minratio > 0) {
26045 rhs[0] = 0.5 * dot(vda, vda);
26046 rhs[1] = 0.5 * dot(vdb, vdb);
26047 rhs[2] = 0.5 * dot(vdc, vdc);
26048 lu_solve(A, 3, indx, rhs, 0);
26049 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
26050 rd = sqrt(dot(rhs, rhs));
26051 if (!useinsertradius) {
26053 elen[0] = dot(vda, vda);
26054 elen[1] = dot(vdb, vdb);
26055 elen[2] = dot(vdc, vdc);
26056 elen[3] = dot(vab, vab);
26057 elen[4] = dot(vbc, vbc);
26058 elen[5] = dot(vca, vca);
26060 for (i = 1; i < 6; i++) {
26061 if (smlen > elen[i]) {
26065 smlen = sqrt(smlen);
26068 if (D > b->minratio) {
26075 if (b->mindihedral > 0) {
26077 for (j = 0; j < 3; j++) {
26078 for (i = 0; i < 3; i++) N[j][i] = 0.0;
26080 lu_solve(A, 3, indx, N[j], 0);
26082 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
26084 for (i = 0; i < 4; i++) {
26085 L[i] = sqrt(dot(N[i], N[i]));
26087 terminatetetgen(
this, 2);
26089 for (j = 0; j < 3; j++) N[i][j] /= L[i];
26092 cosd[0] = -dot(N[0], N[1]);
26093 cosd[1] = -dot(N[0], N[2]);
26094 cosd[2] = -dot(N[0], N[3]);
26095 cosd[3] = -dot(N[1], N[2]);
26096 cosd[4] = -dot(N[1], N[3]);
26097 cosd[5] = -dot(N[2], N[3]);
26101 for (i = 1; i < 6; i++) {
26103 maxcosd = (cosd[i] > maxcosd ? cosd[i] : maxcosd);
26106 if (maxcosd > cosmindihed) {
26110 rhs[0] = 0.5 * dot(vda, vda);
26111 rhs[1] = 0.5 * dot(vdb, vdb);
26112 rhs[2] = 0.5 * dot(vdc, vdc);
26113 lu_solve(A, 3, indx, rhs, 0);
26114 for (i = 0; i < 3; i++) ccent[i] = pd[i] + rhs[i];
26130 int tetgenmesh::splittetrahedron(triface* splittet,
int qflag, REAL *ccent,
26137 insertvertexflags ivf;
26145 makepoint(&newpt, FREEVOLVERTEX);
26146 for (i = 0; i < 3; i++) newpt[i] = ccent[i];
26152 searchtet = *splittet;
26153 ivf.iloc = (int) OUTSIDE;
26154 ivf.iloc = locate(newpt, &searchtet, 1);
26156 if ((ivf.iloc == (
int) OUTSIDE) || (ivf.iloc == (
int) ENCSUBFACE)) {
26159 if (b->verbose > 2) {
26160 printf(
" New point %d is blocked by a polygon.\n", pointmark(newpt));
26163 pointdealloc(newpt);
26164 if (b->nobisect)
return 0;
26169 locateresult sloc = OUTSIDE;
26170 tspivot(searchtet, searchsh);
26171 ppt = (point *) &(searchsh.sh[3]);
26172 projpt2face(ccent, ppt[0], ppt[1], ppt[2], prjpt);
26174 sloc = slocate(prjpt, &searchsh, 0, 0, 1);
26175 if ((sloc == ONEDGE) || (sloc == ONFACE)) {
26178 REAL fcent[3], r = 0;
26179 ppt = (point *) &(searchsh.sh[3]);
26180 if (checkfac4encroach(ppt[0], ppt[1], ppt[2], ccent, fcent, &r)) {
26182 splitflag = splitsubface(&searchsh, NULL, org(*splittet), qflag,
26183 fcent, chkencflag | 2);
26186 repairencfacs(chkencflag | 2);
26190 else if ((sloc == OUTSIDE) || (sloc == ENCSEGMENT)) {
26197 if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) {
26198 enqueuetetrahedron(splittet);
26213 ivf.chkencflag = chkencflag;
26214 ivf.sloc = ivf.sbowywat = 0;
26215 ivf.splitbdflag = 0;
26217 ivf.respectbdflag = 1;
26218 ivf.assignmeshsize = b->metric;
26220 ivf.refineflag = 1;
26221 ivf.refinetet = *splittet;
26222 if (useinsertradius) {
26229 if (insertpoint(newpt, &searchtet, NULL, NULL, &ivf)) {
26232 if (steinerleft > 0) steinerleft--;
26233 if (useinsertradius) {
26234 setpointinsradius(newpt, ivf.smlen);
26235 setpoint2ppt(newpt, ivf.parentpt);
26237 if (flipstack != NULL) {
26238 flipconstraints fc;
26239 fc.chkencflag = chkencflag;
26242 unflipqueue->restart();
26247 pointdealloc(newpt);
26249 if (ivf.iloc == (
int) ENCSEGMENT) {
26250 if (!b->nobisect || checkconstraints) {
26252 for (i = 0; i < encseglist->objects; i++) {
26253 paryseg = (face *) fastlookup(encseglist, i);
26254 if (splitsegment(paryseg, NULL, rv, org(*splittet), NULL, qflag,
26261 encseglist->restart();
26264 if (badsubsegs->items > 0) {
26265 repairencsegs(chkencflag | 3);
26268 if (badsubfacs->items > 0) {
26269 repairencfacs(chkencflag | 2);
26272 }
else if (ivf.iloc == (
int) ENCSUBFACE) {
26273 if (!b->nobisect || checkconstraints) {
26275 for (i = 0; i < encshlist->objects; i++) {
26276 bface = (badface *) fastlookup(encshlist, i);
26277 if (splitsubface(&(bface->ss), NULL, org(*splittet), qflag,
26278 bface->cent, chkencflag | 2)){
26284 encshlist->restart();
26287 if (badsubfacs->items > 0) {
26288 repairencfacs(chkencflag | 2);
26292 if (ivf.iloc == (
int) NEARVERTEX) {
26293 terminatetetgen(
this, 2);
26298 if ((splittet->tet != NULL) && (splittet->tet[4] != NULL)) {
26299 enqueuetetrahedron(splittet);
26314 void tetgenmesh::repairbadtets(
int chkencflag)
26323 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
26324 badtetrahedrons->traversalinit();
26325 bface = (triface *) badtetrahedrons->traverse();
26326 while ((bface != NULL) && (steinerleft != 0)) {
26328 if (bface->ver >= 0) {
26330 if (!isdeadtet(*bface)) {
26332 if (marktest2ed(*bface)) {
26333 unmarktest2(*bface);
26334 if (checktet4split(bface, qflag, ccent)) {
26335 splittetrahedron(bface, qflag, ccent, chkencflag);
26340 badtetrahedrons->dealloc((
void *) bface);
26342 bface = (triface *) badtetrahedrons->traverse();
26346 if (badtetrahedrons->items > 0) {
26347 if (steinerleft == 0) {
26349 printf(
"The desired number of Steiner points is reached.\n");
26352 terminatetetgen(
this, 2);
26355 badtetrahedrons->traversalinit();
26356 bface = (triface *) badtetrahedrons->traverse();
26357 while (bface != NULL) {
26359 if (bface->ver >= 0) {
26360 if (!isdeadtet(*bface)) {
26361 if (marktest2ed(*bface)) {
26362 unmarktest2(*bface);
26366 bface = (triface *) badtetrahedrons->traverse();
26369 badtetrahedrons->restart();
26379 void tetgenmesh::delaunayrefinement()
26387 long bak_segref_count, bak_facref_count, bak_volref_count;
26388 long bak_flipcount = flip23count + flip32count + flip44count;
26391 printf(
"Refining mesh...\n");
26395 printf(
" Min radius-edge ratio = %g.\n", b->minratio);
26396 printf(
" Min dihedral angle = %g.\n", b->mindihedral);
26400 steinerleft = b->steinerleft;
26401 if (steinerleft > 0) {
26403 steinercount = st_segref_count + st_facref_count + st_volref_count;
26404 if (steinercount < steinerleft) {
26405 steinerleft -= steinercount;
26408 printf(
"\nWarning: ");
26409 printf(
"The desired number of Steiner points (%d) has reached.\n\n",
26416 if (useinsertradius) {
26417 if ((b->plc && b->nobisect) || b->refine) {
26418 makesegmentendpointsmap();
26419 makefacetverticesmap();
26424 encseglist =
new arraypool(
sizeof(face), 8);
26425 encshlist =
new arraypool(
sizeof(badface), 8);
26429 if (!b->nobisect || checkconstraints) {
26431 printf(
" Splitting encroached subsegments.\n");
26435 steinercount = points->items;
26438 badsubsegs =
new memorypool(
sizeof(face), b->shellfaceperblock,
26439 sizeof(
void *), 0);
26442 subsegs->traversalinit();
26443 checkseg.sh = shellfacetraverse(subsegs);
26444 while (checkseg.sh != (shellface *) NULL) {
26445 enqueuesubface(badsubsegs, &checkseg);
26446 checkseg.sh = shellfacetraverse(subsegs);
26450 repairencsegs(chkencflag);
26453 printf(
" Added %ld Steiner points.\n", points->items - steinercount);
26456 if (b->reflevel > 1) {
26458 printf(
" Splitting encroached subfaces.\n");
26462 steinercount = points->items;
26463 bak_segref_count = st_segref_count;
26464 bak_facref_count = st_facref_count;
26467 badsubfacs =
new memorypool(
sizeof(face), b->shellfaceperblock,
26468 sizeof(
void *), 0);
26471 subfaces->traversalinit();
26472 checksh.sh = shellfacetraverse(subfaces);
26473 while (checksh.sh != (shellface *) NULL) {
26474 enqueuesubface(badsubfacs, &checksh);
26475 checksh.sh = shellfacetraverse(subfaces);
26479 repairencfacs(chkencflag);
26482 printf(
" Added %ld (%ld,%ld) Steiner points.\n",
26483 points->items-steinercount, st_segref_count-bak_segref_count,
26484 st_facref_count-bak_facref_count);
26489 if (b->reflevel > 2) {
26491 printf(
" Splitting bad quality tets.\n");
26495 steinercount = points->items;
26496 bak_segref_count = st_segref_count;
26497 bak_facref_count = st_facref_count;
26498 bak_volref_count = st_volref_count;
26501 cosmindihed = cos(b->mindihedral / 180.0 * PI);
26504 badtetrahedrons =
new memorypool(
sizeof(triface), b->tetrahedraperblock,
26505 sizeof(
void *), 0);
26507 tetrahedrons->traversalinit();
26508 checktet.tet = tetrahedrontraverse();
26509 while (checktet.tet != NULL) {
26510 enqueuetetrahedron(&checktet);
26511 checktet.tet = tetrahedrontraverse();
26515 repairbadtets(chkencflag);
26518 printf(
" Added %ld (%ld,%ld,%ld) Steiner points.\n",
26519 points->items - steinercount,
26520 st_segref_count - bak_segref_count,
26521 st_facref_count - bak_facref_count,
26522 st_volref_count - bak_volref_count);
26527 if (flip23count + flip32count + flip44count > bak_flipcount) {
26528 printf(
" Performed %ld flips.\n", flip23count + flip32count +
26529 flip44count - bak_flipcount);
26533 if (steinerleft == 0) {
26535 printf(
"\nWarnning: ");
26536 printf(
"The desired number of Steiner points (%d) is reached.\n\n",
26547 if (!b->nobisect || checkconstraints) {
26548 totalworkmemory += (badsubsegs->maxitems * badsubsegs->itembytes);
26551 if (b->reflevel > 1) {
26552 totalworkmemory += (badsubfacs->maxitems * badsubfacs->itembytes);
26557 if (b->reflevel > 2) {
26558 totalworkmemory += (badtetrahedrons->maxitems*badtetrahedrons->itembytes);
26559 delete badtetrahedrons;
26560 badtetrahedrons = NULL;
26578 long tetgenmesh::lawsonflip3d(flipconstraints *fc)
26580 triface fliptets[5], neightet, hulltet;
26581 face checksh, casingout;
26582 badface *popface, *bface;
26583 point pd, pe, *pts;
26586 long flipcount, totalcount = 0l;
26587 long sliver_peels = 0l;
26594 if (b->verbose > 2) {
26595 printf(
" Lawson flip %ld faces.\n", flippool->items);
26599 while (flipstack != (badface *) NULL) {
26601 popface = flipstack;
26602 fliptets[0] = popface->tt;
26603 flipstack = flipstack->nextitem;
26604 flippool->dealloc((
void *) popface);
26607 if (isdeadtet(fliptets[0]))
continue;
26609 if (!facemarked(fliptets[0]))
continue;
26611 unmarkface(fliptets[0]);
26613 if (ishulltet(fliptets[0]))
continue;
26615 fsym(fliptets[0], fliptets[1]);
26616 if (ishulltet(fliptets[1])) {
26619 tspivot(fliptets[0], checksh);
26620 for (i = 0; i < 3; i++) {
26621 if (!isshsubseg(checksh)) {
26622 spivot(checksh, casingout);
26624 if (sorg(checksh) != sdest(casingout)) sesymself(casingout);
26625 stpivot(casingout, neightet);
26626 if (neightet.tet == fliptets[0].tet) {
26629 edestoppo(neightet, hulltet);
26631 if (oppo(hulltet) == dummypoint) {
26632 pe = org(neightet);
26633 if ((pointtype(pe) == FREEFACETVERTEX) ||
26634 (pointtype(pe) == FREESEGVERTEX)) {
26635 removevertexbyflips(pe);
26638 eorgoppo(neightet, hulltet);
26640 if (oppo(hulltet) == dummypoint) {
26641 pd = dest(neightet);
26642 if ((pointtype(pd) == FREEFACETVERTEX) ||
26643 (pointtype(pd) == FREESEGVERTEX)) {
26644 removevertexbyflips(pd);
26648 fliptets[0] = neightet;
26649 fnext(fliptets[0], fliptets[1]);
26650 fnext(fliptets[1], fliptets[2]);
26651 flip32(fliptets, 1, fc);
26656 if (fc->remove_ndelaunay_edge) {
26659 tetprism_vol_sum += fc->tetprism_vol_sum;
26660 fc->tetprism_vol_sum = 0.0;
26667 senextself(checksh);
26673 if (checksubfaceflag) {
26675 if (issubface(fliptets[0]))
continue;
26679 pts = (point *) fliptets[1].tet;
26680 sign = insphere_s(pts[4], pts[5], pts[6], pts[7], oppo(fliptets[0]));
26684 pd = oppo(fliptets[0]);
26685 pe = oppo(fliptets[1]);
26689 len3 = distance(pd, pe);
26690 len3 = (len3 * len3 * len3);
26691 int round_flag = 0;
26695 for (i = 0; i < 3; i++) {
26696 ori = orient3d(org(fliptets[0]), dest(fliptets[0]), pd, pe);
26700 esym(fliptets[0], fliptets[2]);
26701 esym(fliptets[1], fliptets[3]);
26702 if (issubface(fliptets[2]) || issubface(fliptets[3])) {
26703 vol = orient3dfast(org(fliptets[0]), dest(fliptets[0]), pd, pe);
26704 if ((fabs(vol) / len3) < b->epsilon) {
26710 if (ori <= 0)
break;
26711 enextself(fliptets[0]);
26712 eprevself(fliptets[1]);
26719 flip23(fliptets, 0, fc);
26721 if (fc->remove_ndelaunay_edge) {
26724 tetprism_vol_sum += fc->tetprism_vol_sum;
26725 fc->tetprism_vol_sum = 0.0;
26731 if (checksubsegflag) {
26733 if (issubseg(fliptets[0]))
continue;
26736 esymself(fliptets[0]);
26737 for (i = 0; i < 3; i++) {
26738 fnext(fliptets[i], fliptets[i+1]);
26740 if (fliptets[3].tet == fliptets[0].tet) {
26742 flip32(fliptets, 0, fc);
26744 if (fc->remove_ndelaunay_edge) {
26747 tetprism_vol_sum += fc->tetprism_vol_sum;
26748 fc->tetprism_vol_sum = 0.0;
26753 fnext(fliptets[3], fliptets[4]);
26754 if (fliptets[4].tet == fliptets[0].tet) {
26756 if (round_flag == 1) {
26760 if (apex(fliptets[3]) == dummypoint) {
26773 esymself(fliptets[0]);
26777 flip23(fliptets, 0, fc);
26778 fnext(fliptets[3], fliptets[1]);
26779 fnext(fliptets[1], fliptets[2]);
26787 flip32(&(fliptets[1]), (apex(fliptets[3]) == dummypoint), fc);
26792 if (fc->remove_ndelaunay_edge) {
26795 tetprism_vol_sum += fc->tetprism_vol_sum;
26796 fc->tetprism_vol_sum = 0.0;
26809 unflipqueue->newindex((
void **) &bface);
26810 bface->tt = fliptets[0];
26811 bface->forg = org(fliptets[0]);
26812 bface->fdest = dest(fliptets[0]);
26813 bface->fapex = apex(fliptets[0]);
26817 if (b->verbose > 2) {
26818 if (flipcount > 0) {
26819 printf(
" Performed %ld flips.\n", flipcount);
26823 totalcount += flipcount;
26826 if (unflipqueue->objects == 0l)
break;
26828 if (flipcount == 0l)
break;
26831 for (i = 0; i < unflipqueue->objects; i++) {
26832 bface = (badface *) fastlookup(unflipqueue, i);
26833 if (!isdeadtet(bface->tt) &&
26834 (org(bface->tt) == bface->forg) &&
26835 (dest(bface->tt) == bface->fdest) &&
26836 (apex(bface->tt) == bface->fapex)) {
26837 flippush(flipstack, &(bface->tt));
26840 unflipqueue->restart();
26844 if (b->verbose > 2) {
26845 if (totalcount > 0) {
26846 printf(
" Performed %ld flips.\n", totalcount);
26848 if (sliver_peels > 0) {
26849 printf(
" Removed %ld hull slivers.\n", sliver_peels);
26851 if (unflipqueue->objects > 0l) {
26852 printf(
" %ld unflippable edges remained.\n", unflipqueue->objects);
26856 return totalcount + sliver_peels;
26865 void tetgenmesh::recoverdelaunay()
26867 arraypool *flipqueue, *nextflipqueue, *swapqueue;
26868 triface tetloop, neightet, *parytet;
26869 badface *bface, *parybface;
26871 flipconstraints fc;
26875 printf(
"Recovering Delaunayness...\n");
26878 tetprism_vol_sum = 0.0;
26881 tetrahedrons->traversalinit();
26882 tetloop.tet = tetrahedrontraverse();
26883 while (tetloop.tet != NULL) {
26884 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
26885 decode(tetloop.tet[tetloop.ver], neightet);
26886 if (!facemarked(neightet)) {
26887 flippush(flipstack, &tetloop);
26890 ppt = (point *) &(tetloop.tet[4]);
26891 tetprism_vol_sum += tetprismvol(ppt[0], ppt[1], ppt[2], ppt[3]);
26892 tetloop.tet = tetrahedrontraverse();
26897 fc.bak_tetprism_vol = tetprism_vol_sum * b->epsilon * 1e-3;
26900 printf(
" Initial obj = %.17g\n", tetprism_vol_sum);
26903 if (b->verbose > 1) {
26904 printf(
" Recover Delaunay [Lawson] : %ld\n", flippool->items);
26908 fc.remove_ndelaunay_edge = 1;
26913 if (b->verbose > 1) {
26914 printf(
" obj (after Lawson) = %.17g\n", tetprism_vol_sum);
26917 if (unflipqueue->objects == 0l) {
26922 fc.collectnewtets = 1;
26925 autofliplinklevel = 1;
26926 b->fliplinklevel = -1;
26929 int bakmaxflipstarsize = b->flipstarsize;
26930 b->flipstarsize = 10;
26932 flipqueue =
new arraypool(
sizeof(badface), 10);
26933 nextflipqueue =
new arraypool(
sizeof(badface), 10);
26936 swapqueue = flipqueue;
26937 flipqueue = unflipqueue;
26938 unflipqueue = swapqueue;
26940 while (flipqueue->objects > 0l) {
26942 if (b->verbose > 1) {
26943 printf(
" Recover Delaunay [level = %2d] #: %ld.\n",
26944 autofliplinklevel, flipqueue->objects);
26947 for (i = 0; i < flipqueue->objects; i++) {
26948 bface = (badface *) fastlookup(flipqueue, i);
26949 if (getedge(bface->forg, bface->fdest, &bface->tt)) {
26950 if (removeedgebyflips(&(bface->tt), &fc) == 2) {
26951 tetprism_vol_sum += fc.tetprism_vol_sum;
26952 fc.tetprism_vol_sum = 0.0;
26954 for (j = 0; j < cavetetlist->objects; j++) {
26955 parytet = (triface *) fastlookup(cavetetlist, j);
26957 if (!isdeadtet(*parytet)) {
26958 for (parytet->ver = 0; parytet->ver < 4; parytet->ver++) {
26960 decode(parytet->tet[parytet->ver], neightet);
26961 if (!facemarked(neightet)) {
26962 flippush(flipstack, parytet);
26967 cavetetlist->restart();
26974 for (j = 0; j < unflipqueue->objects; j++) {
26975 bface = (badface *) fastlookup(unflipqueue, j);
26976 flipqueue->newindex((
void **) &parybface);
26977 *parybface = *bface;
26979 unflipqueue->restart();
26982 nextflipqueue->newindex((
void **) &parybface);
26983 *parybface = *bface;
26987 fc.tetprism_vol_sum = 0.0;
26992 if (b->verbose > 1) {
26993 printf(
" obj (after level %d) = %.17g.\n", autofliplinklevel,
26996 flipqueue->restart();
26999 swapqueue = flipqueue;
27000 flipqueue = nextflipqueue;
27001 nextflipqueue = swapqueue;
27003 if (flipqueue->objects > 0l) {
27005 if (autofliplinklevel >= b->delmaxfliplevel) {
27009 autofliplinklevel+=b->fliplinklevelinc;
27013 if (flipqueue->objects > 0l) {
27014 if (b->verbose > 1) {
27015 printf(
" %ld non-Delaunay edges remained.\n", flipqueue->objects);
27020 printf(
" Final obj = %.17g\n", tetprism_vol_sum);
27023 b->flipstarsize = bakmaxflipstarsize;
27025 delete nextflipqueue;
27034 int tetgenmesh::gettetrahedron(point pa, point pb, point pc, point pd,
27035 triface *searchtet)
27040 if (getedge(pa, pb, searchtet)) {
27041 spintet = *searchtet;
27043 if (apex(spintet) == pc) {
27044 *searchtet = spintet;
27047 fnextself(spintet);
27048 if (spintet.tet == searchtet->tet)
break;
27050 if (apex(*searchtet) == pc) {
27051 if (oppo(*searchtet) == pd) {
27054 fsymself(*searchtet);
27055 if (oppo(*searchtet) == pd) {
27071 long tetgenmesh::improvequalitybyflips()
27073 arraypool *flipqueue, *nextflipqueue, *swapqueue;
27074 badface *bface, *parybface;
27077 flipconstraints fc;
27078 REAL *cosdd, ncosdd[6], maxdd;
27079 long totalremcount, remcount;
27084 flipqueue =
new arraypool(
sizeof(badface), 10);
27085 nextflipqueue =
new arraypool(
sizeof(badface), 10);
27088 int bakautofliplinklevel = autofliplinklevel;
27089 int bakfliplinklevel = b->fliplinklevel;
27090 int bakmaxflipstarsize = b->flipstarsize;
27093 autofliplinklevel = 1;
27094 b->fliplinklevel = -1;
27095 b->flipstarsize = 10;
27097 fc.remove_large_angle = 1;
27099 fc.collectnewtets = 1;
27100 fc.checkflipeligibility = 1;
27102 totalremcount = 0l;
27105 swapqueue = flipqueue;
27106 flipqueue = unflipqueue;
27107 unflipqueue = swapqueue;
27109 while (flipqueue->objects > 0l) {
27113 while (flipqueue->objects > 0l) {
27114 if (b->verbose > 1) {
27115 printf(
" Improving mesh qualiy by flips [%d]#: %ld.\n",
27116 autofliplinklevel, flipqueue->objects);
27119 for (k = 0; k < flipqueue->objects; k++) {
27120 bface = (badface *) fastlookup(flipqueue, k);
27121 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27122 bface->foppo, &bface->tt)) {
27125 if (bface->tt.ver != 11) {
27128 ppt = (point *) & (bface->tt.tet[4]);
27129 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27130 &bface->key, NULL);
27131 bface->forg = ppt[0];
27132 bface->fdest = ppt[1];
27133 bface->fapex = ppt[2];
27134 bface->foppo = ppt[3];
27135 bface->tt.ver = 11;
27137 if (bface->key == 0) {
27139 ppt = (point *) & (bface->tt.tet[4]);
27140 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27141 &bface->key, NULL);
27143 cosdd = bface->cent;
27145 for (i = 0; (i < 6) && !remflag; i++) {
27146 if (cosdd[i] < cosmaxdihed) {
27148 bface->tt.ver = edge2ver[i];
27149 fc.cosdihed_in = cosdd[i];
27150 fc.cosdihed_out = 0.0;
27151 n = removeedgebyflips(&(bface->tt), &fc);
27155 if (fc.cosdihed_out < cosmaxdihed) {
27157 for (j = 0; j < cavetetlist->objects; j++) {
27158 parytet = (triface *) fastlookup(cavetetlist, j);
27159 if (!isdeadtet(*parytet)) {
27160 ppt = (point *) & (parytet->tet[4]);
27162 if (ppt[3] != dummypoint) {
27163 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd,
27165 if (maxdd < cosmaxdihed) {
27167 nextflipqueue->newindex((
void **) &parybface);
27168 parybface->tt.tet = parytet->tet;
27169 parybface->tt.ver = 11;
27170 parybface->forg = ppt[0];
27171 parybface->fdest = ppt[1];
27172 parybface->fapex = ppt[2];
27173 parybface->foppo = ppt[3];
27174 parybface->key = maxdd;
27175 for (n = 0; n < 6; n++) {
27176 parybface->cent[n] = ncosdd[n];
27183 cavetetlist->restart();
27190 unflipqueue->newindex((
void **) &parybface);
27191 *parybface = *bface;
27196 flipqueue->restart();
27199 swapqueue = flipqueue;
27200 flipqueue = nextflipqueue;
27201 nextflipqueue = swapqueue;
27204 if (b->verbose > 1) {
27205 printf(
" Removed %ld bad tets.\n", remcount);
27207 totalremcount += remcount;
27209 if (unflipqueue->objects > 0l) {
27211 if (autofliplinklevel >= b->optlevel) {
27214 autofliplinklevel+=b->fliplinklevelinc;
27219 swapqueue = flipqueue;
27220 flipqueue = unflipqueue;
27221 unflipqueue = swapqueue;
27225 autofliplinklevel = bakautofliplinklevel;
27226 b->fliplinklevel = bakfliplinklevel;
27227 b->flipstarsize = bakmaxflipstarsize;
27230 delete nextflipqueue;
27232 return totalremcount;
27261 int tetgenmesh::smoothpoint(point smtpt, arraypool *linkfacelist,
int ccw,
27262 optparameters *opm)
27264 triface *parytet, *parytet1, swaptet;
27266 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
27267 REAL oldval, minval = 0.0, val;
27274 numdirs = (int) linkfacelist->objects;
27275 if (numdirs > opm->numofsearchdirs) {
27276 numdirs = opm->numofsearchdirs;
27280 opm->imprval = opm->initval;
27283 for (i = 0; i < 3; i++) {
27284 bestpt[i] = startpt[i] = smtpt[i];
27291 oldval = opm->imprval;
27293 for (i = 0; i < numdirs; i++) {
27295 k = (int) randomnation(linkfacelist->objects - i);
27296 parytet = (triface *) fastlookup(linkfacelist, k);
27298 pa = org(*parytet);
27299 pb = dest(*parytet);
27300 pc = apex(*parytet);
27301 for (j = 0; j < 3; j++) {
27302 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
27304 for (j = 0; j < 3; j++) {
27305 nextpt[j] = startpt[j] + opm->searchstep * (fcent[j] - startpt[j]);
27308 for (j = 0; j < linkfacelist->objects; j++) {
27309 parytet = (triface *) fastlookup(linkfacelist, j);
27311 pa = org(*parytet);
27312 pb = dest(*parytet);
27314 pb = org(*parytet);
27315 pa = dest(*parytet);
27317 pc = apex(*parytet);
27318 ori = orient3d(pa, pb, pc, nextpt);
27321 if (opm->max_min_volume) {
27323 val = - orient3dfast(pa, pb, pc, nextpt);
27324 }
else if (opm->min_max_aspectratio) {
27325 val = 1.0 / tetaspectratio(pa, pb, pc, nextpt);
27326 }
else if (opm->min_max_dihedangle) {
27327 tetalldihedral(pa, pb, pc, nextpt, NULL, &maxcosd, NULL);
27328 if (maxcosd < -1) maxcosd = -1.0;
27329 val = maxcosd + 1.0;
27337 if (opm->max_min_volume) {
27339 val = - orient3dfast(pa, pb, pc, nextpt);
27346 if (val <= opm->imprval) {
27353 minval = (val < minval) ? val : minval;
27357 if (j == linkfacelist->objects) {
27359 opm->imprval = minval;
27361 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
27364 j = linkfacelist->objects - i - 1;
27365 parytet = (triface *) fastlookup(linkfacelist, k);
27366 parytet1 = (triface *) fastlookup(linkfacelist, j);
27367 swaptet = *parytet1;
27368 *parytet1 = *parytet;
27369 *parytet = swaptet;
27372 diff = opm->imprval - oldval;
27375 if (opm->max_min_volume) {
27377 }
else if (opm->min_max_aspectratio) {
27378 if ((diff / oldval) < 1e-3) diff = 0.0;
27379 }
else if (opm->min_max_dihedangle) {
27385 terminatetetgen(
this, 2);
27391 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
27393 if ((opm->maxiter > 0) && (iter >= opm->maxiter)) {
27405 opm->smthiter = iter;
27407 for (i = 0; i < 3; i++) smtpt[i] = startpt[i];
27420 long tetgenmesh::improvequalitybysmoothing(optparameters *opm)
27422 arraypool *flipqueue, *swapqueue;
27424 badface *bface, *parybface;
27426 long totalsmtcount, smtcount;
27431 flipqueue =
new arraypool(
sizeof(badface), 10);
27434 swapqueue = flipqueue;
27435 flipqueue = unflipqueue;
27436 unflipqueue = swapqueue;
27438 totalsmtcount = 0l;
27441 while (flipqueue->objects > 0l) {
27445 if (b->verbose > 1) {
27446 printf(
" Improving mesh quality by smoothing [%d]#: %ld.\n",
27447 iter, flipqueue->objects);
27450 for (k = 0; k < flipqueue->objects; k++) {
27451 bface = (badface *) fastlookup(flipqueue, k);
27452 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27453 bface->foppo, &bface->tt)) {
27455 if (!marktested(bface->tt)) {
27458 ppt = (point *) & (bface->tt.tet[4]);
27459 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27460 &bface->key, NULL);
27461 if (bface->key < cossmtdihed) {
27464 opm->initval = bface->key + 1.0;
27465 for (i = 0; (i < 4) && !smtflag; i++) {
27466 if (pointtype(ppt[i]) == FREEVOLVERTEX) {
27467 getvertexstar(1, ppt[i], cavetetlist, NULL, NULL);
27468 opm->searchstep = 0.001;
27469 smtflag = smoothpoint(ppt[i], cavetetlist, 1, opm);
27471 while (opm->smthiter == opm->maxiter) {
27472 opm->searchstep *= 10.0;
27473 opm->initval = opm->imprval;
27475 smoothpoint(ppt[i], cavetetlist, 1, opm);
27479 if ((opm->imprval - 1.0) < cossmtdihed) {
27481 for (j = 0; j < cavetetlist->objects; j++) {
27482 parytet = (triface *) fastlookup(cavetetlist, j);
27484 if (!marktested(*parytet)) {
27487 ppt = (point *) & (parytet->tet[4]);
27488 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3],
27489 bface->cent, &bface->key, NULL);
27490 if (bface->key < cossmtdihed) {
27492 marktest(*parytet);
27493 unflipqueue->newindex((
void **) &parybface);
27494 parybface->tt = *parytet;
27495 parybface->forg = ppt[0];
27496 parybface->fdest = ppt[1];
27497 parybface->fapex = ppt[2];
27498 parybface->foppo = ppt[3];
27499 parybface->tt.ver = 11;
27500 parybface->key = 0.0;
27506 cavetetlist->restart();
27511 marktest(bface->tt);
27512 unflipqueue->newindex((
void **) &parybface);
27513 parybface->tt = bface->tt;
27514 parybface->forg = ppt[0];
27515 parybface->fdest = ppt[1];
27516 parybface->fapex = ppt[2];
27517 parybface->foppo = ppt[3];
27518 parybface->tt.ver = 11;
27519 parybface->key = 0.0;
27526 flipqueue->restart();
27529 for (i = 0; i < unflipqueue->objects; i++) {
27530 bface = (badface *) fastlookup(unflipqueue, i);
27531 unmarktest(bface->tt);
27534 if (b->verbose > 1) {
27535 printf(
" Smooth %ld points.\n", smtcount);
27537 totalsmtcount += smtcount;
27539 if (smtcount == 0l) {
27550 swapqueue = flipqueue;
27551 flipqueue = unflipqueue;
27552 unflipqueue = swapqueue;
27557 return totalsmtcount;
27566 int tetgenmesh::splitsliver(triface *slitet, REAL cosd,
int chkencflag)
27569 triface searchtet, spintet, *parytet;
27570 point pa, pb, steinerpt;
27572 insertvertexflags ivf;
27573 REAL smtpt[3], midpt[3];
27580 edestoppo(*slitet, searchtet);
27583 if (issubseg(searchtet)) {
27589 spintet = searchtet;
27592 if (ishulltet(spintet))
break;
27594 fnextself(spintet);
27595 if (spintet.tet == searchtet.tet)
break;
27597 if (ishulltet(spintet)) {
27602 abtets =
new triface[n];
27603 spintet = searchtet;
27604 for (i = 0; i < n; i++) {
27605 abtets[i] = spintet;
27606 fnextself(spintet);
27610 for (i = 0; i < n; i++) {
27611 eprev(abtets[i], searchtet);
27612 esymself(searchtet);
27613 cavetetlist->newindex((
void **) &parytet);
27614 *parytet = searchtet;
27615 enext(abtets[i], searchtet);
27616 esymself(searchtet);
27617 cavetetlist->newindex((
void **) &parytet);
27618 *parytet = searchtet;
27622 pa = org(abtets[0]);
27623 pb = dest(abtets[0]);
27624 for (i = 0; i < 3; i++) {
27625 smtpt[i] = midpt[i] = 0.5 * (pa[i] + pb[i]);
27629 opm.min_max_dihedangle = 1;
27630 opm.initval = cosd + 1.0;
27631 opm.numofsearchdirs = 20;
27632 opm.searchstep = 0.001;
27635 success = smoothpoint(smtpt, cavetetlist, 1, &opm);
27638 while (opm.smthiter == opm.maxiter) {
27641 opm.searchstep *= 10.0;
27643 opm.initval = opm.imprval;
27645 smoothpoint(smtpt, cavetetlist, 1, &opm);
27649 cavetetlist->restart();
27658 makepoint(&steinerpt, FREEVOLVERTEX);
27659 for (i = 0; i < 3; i++) steinerpt[i] = smtpt[i];
27662 for (i = 0; i < n; i++) {
27664 caveoldtetlist->newindex((
void **) &parytet);
27665 *parytet = abtets[i];
27668 searchtet = abtets[0];
27670 locate(steinerpt, &searchtet);
27675 ivf.iloc = (int) INSTAR;
27676 ivf.chkencflag = chkencflag;
27677 ivf.assignmeshsize = b->metric;
27680 if (insertpoint(steinerpt, &searchtet, NULL, NULL, &ivf)) {
27683 if (steinerleft > 0) steinerleft--;
27687 pointdealloc(steinerpt);
27698 long tetgenmesh::removeslivers(
int chkencflag)
27700 arraypool *flipqueue, *swapqueue;
27701 badface *bface, *parybface;
27702 triface slitet, *parytet;
27704 REAL cosdd[6], maxcosd;
27705 long totalsptcount, sptcount;
27709 flipqueue =
new arraypool(
sizeof(badface), 10);
27712 swapqueue = flipqueue;
27713 flipqueue = unflipqueue;
27714 unflipqueue = swapqueue;
27716 totalsptcount = 0l;
27719 while ((flipqueue->objects > 0l) && (steinerleft != 0)) {
27723 if (b->verbose > 1) {
27724 printf(
" Splitting bad quality tets [%d]#: %ld.\n",
27725 iter, flipqueue->objects);
27728 for (k = 0; (k < flipqueue->objects) && (steinerleft != 0); k++) {
27729 bface = (badface *) fastlookup(flipqueue, k);
27730 if (gettetrahedron(bface->forg, bface->fdest, bface->fapex,
27731 bface->foppo, &bface->tt)) {
27732 if ((bface->key == 0) || (bface->tt.ver != 11)) {
27735 ppt = (point *) & (bface->tt.tet[4]);
27736 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], bface->cent,
27737 &bface->key, NULL);
27739 if (bface->key < cosslidihed) {
27741 slitet.tet = bface->tt.tet;
27743 for (j = 0; j < 6; j++) {
27744 if (bface->cent[j] < cosslidihed) {
27746 slitet.ver = edge2ver[j];
27747 if (splitsliver(&slitet, bface->cent[j], chkencflag)) {
27755 badtetrahedrons->traversalinit();
27756 parytet = (triface *) badtetrahedrons->traverse();
27757 while (parytet != NULL) {
27758 unmarktest2(*parytet);
27759 ppt = (point *) & (parytet->tet[4]);
27760 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], cosdd,
27762 if (maxcosd < cosslidihed) {
27764 unflipqueue->newindex((
void **) &parybface);
27765 parybface->forg = ppt[0];
27766 parybface->fdest = ppt[1];
27767 parybface->fapex = ppt[2];
27768 parybface->foppo = ppt[3];
27769 parybface->tt.tet = parytet->tet;
27770 parybface->tt.ver = 11;
27771 parybface->key = maxcosd;
27772 for (i = 0; i < 6; i++) {
27773 parybface->cent[i] = cosdd[i];
27776 parytet = (triface *) badtetrahedrons->traverse();
27778 badtetrahedrons->restart();
27781 unflipqueue->newindex((
void **) &parybface);
27782 *parybface = *bface;
27788 flipqueue->restart();
27790 if (b->verbose > 1) {
27791 printf(
" Split %ld tets.\n", sptcount);
27793 totalsptcount += sptcount;
27795 if (sptcount == 0l) {
27806 swapqueue = flipqueue;
27807 flipqueue = unflipqueue;
27808 unflipqueue = swapqueue;
27813 return totalsptcount;
27822 void tetgenmesh::optimizemesh()
27824 badface *parybface;
27829 REAL ncosdd[6], maxdd;
27830 long totalremcount, remcount;
27831 long totalsmtcount, smtcount;
27832 long totalsptcount, sptcount;
27838 printf(
"Optimizing mesh...\n");
27841 optpasses = ((1 << b->optlevel) - 1);
27844 printf(
" Optimization level = %d.\n", b->optlevel);
27845 printf(
" Optimization scheme = %d.\n", b->optscheme);
27846 printf(
" Number of iteration = %d.\n", optpasses);
27847 printf(
" Min_Max dihed angle = %g.\n", b->optmaxdihedral);
27850 totalsmtcount = totalsptcount = totalremcount = 0l;
27852 cosmaxdihed = cos(b->optmaxdihedral / 180.0 * PI);
27853 cossmtdihed = cos(b->optminsmtdihed / 180.0 * PI);
27854 cosslidihed = cos(b->optminslidihed / 180.0 * PI);
27856 int attrnum = numelemattrib - 1;
27859 tetrahedrons->traversalinit();
27860 checktet.tet = tetrahedrontraverse();
27861 while (checktet.tet != NULL) {
27864 if (elemattribute(checktet.tet, attrnum) == -1.0) {
27865 checktet.tet = tetrahedrontraverse();
27869 ppt = (point *) & (checktet.tet[4]);
27870 tetalldihedral(ppt[0], ppt[1], ppt[2], ppt[3], ncosdd, &maxdd, NULL);
27871 if (maxdd < cosmaxdihed) {
27873 unflipqueue->newindex((
void **) &parybface);
27874 parybface->tt.tet = checktet.tet;
27875 parybface->tt.ver = 11;
27876 parybface->forg = ppt[0];
27877 parybface->fdest = ppt[1];
27878 parybface->fapex = ppt[2];
27879 parybface->foppo = ppt[3];
27880 parybface->key = maxdd;
27881 for (n = 0; n < 6; n++) {
27882 parybface->cent[n] = ncosdd[n];
27885 checktet.tet = tetrahedrontraverse();
27888 totalremcount = improvequalitybyflips();
27890 if ((unflipqueue->objects > 0l) &&
27891 ((b->optscheme & 2) || (b->optscheme & 4))) {
27893 badtetrahedrons =
new memorypool(
sizeof(triface), b->tetrahedraperblock,
27894 sizeof(
void *), 0);
27897 opm.min_max_dihedangle = 1;
27898 opm.numofsearchdirs = 10;
27905 while (iter < optpasses) {
27906 smtcount = sptcount = remcount = 0l;
27907 if (b->optscheme & 2) {
27908 smtcount += improvequalitybysmoothing(&opm);
27909 totalsmtcount += smtcount;
27910 if (smtcount > 0l) {
27911 remcount = improvequalitybyflips();
27912 totalremcount += remcount;
27915 if (unflipqueue->objects > 0l) {
27916 if (b->optscheme & 4) {
27917 sptcount += removeslivers(chkencflag);
27918 totalsptcount += sptcount;
27919 if (sptcount > 0l) {
27920 remcount = improvequalitybyflips();
27921 totalremcount += remcount;
27925 if (unflipqueue->objects > 0l) {
27926 if (remcount > 0l) {
27936 delete badtetrahedrons;
27937 badtetrahedrons = NULL;
27940 if (unflipqueue->objects > 0l) {
27941 if (b->verbose > 1) {
27942 printf(
" %ld bad tets remained.\n", unflipqueue->objects);
27944 unflipqueue->restart();
27948 if (totalremcount > 0l) {
27949 printf(
" Removed %ld edges.\n", totalremcount);
27951 if (totalsmtcount > 0l) {
27952 printf(
" Smoothed %ld points.\n", totalsmtcount);
27954 if (totalsptcount > 0l) {
27955 printf(
" Split %ld slivers.\n", totalsptcount);
27976 void tetgenmesh::printfcomma(
unsigned long n)
27978 unsigned long n2 = 0;
27980 while (n >= 1000) {
27981 n2 = n2 + scale * (n % 1000);
27986 while (scale != 1) {
27990 printf (
",%03ld", n);
28003 int tetgenmesh::checkmesh(
int topoflag)
28005 triface tetloop, neightet, symtet;
28006 point pa, pb, pc, pd;
28011 printf(
" Checking consistency of mesh...\n");
28017 tetrahedrons->traversalinit();
28018 tetloop.tet = alltetrahedrontraverse();
28019 while (tetloop.tet != (tetrahedron *) NULL) {
28021 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28023 pb = dest(tetloop);
28024 pc = apex(tetloop);
28025 pd = oppo(tetloop);
28026 if (tetloop.ver == 0) {
28027 if (!ishulltet(tetloop)) {
28029 ori = orient3d(pa, pb, pc, pd);
28031 printf(
" !! !! %s ", ori > 0.0 ?
"Inverted" :
"Degenerated");
28032 printf(
" (%d, %d, %d, %d) (ori = %.17g)\n", pointmark(pa),
28033 pointmark(pb), pointmark(pc), pointmark(pd), ori);
28038 if (infected(tetloop)) {
28040 printf(
" !! (%d, %d, %d, %d) is infected.\n", pointmark(pa),
28041 pointmark(pb), pointmark(pc), pointmark(pd));
28044 if (marktested(tetloop)) {
28046 printf(
" !! (%d, %d, %d, %d) is marked.\n", pointmark(pa),
28047 pointmark(pb), pointmark(pc), pointmark(pd));
28051 if (tetloop.tet[tetloop.ver] == NULL) {
28052 printf(
" !! !! No neighbor at face (%d, %d, %d).\n", pointmark(pa),
28053 pointmark(pb), pointmark(pc));
28057 fsym(tetloop, neightet);
28058 if (neightet.tet != NULL) {
28060 fsym(neightet, symtet);
28061 if ((tetloop.tet != symtet.tet) || (tetloop.ver != symtet.ver)) {
28062 printf(
" !! !! Asymmetric tetra-tetra bond:\n");
28063 if (tetloop.tet == symtet.tet) {
28064 printf(
" (Right tetrahedron, wrong orientation)\n");
28066 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28067 pointmark(pb), pointmark(pc), pointmark(pd));
28068 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28069 pointmark(dest(neightet)), pointmark(apex(neightet)),
28070 pointmark(oppo(neightet)));
28074 if ((org(neightet) != pb) || (dest(neightet) != pa)) {
28075 printf(
" !! !! Wrong edge-edge bond:\n");
28076 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28077 pointmark(pb), pointmark(pc), pointmark(pd));
28078 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28079 pointmark(dest(neightet)), pointmark(apex(neightet)),
28080 pointmark(oppo(neightet)));
28084 if (apex(neightet) != pc) {
28085 printf(
" !! !! Wrong face-face bond:\n");
28086 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28087 pointmark(pb), pointmark(pc), pointmark(pd));
28088 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28089 pointmark(dest(neightet)), pointmark(apex(neightet)),
28090 pointmark(oppo(neightet)));
28094 if (oppo(neightet) == pd) {
28095 printf(
" !! !! Two identical tetra:\n");
28096 printf(
" First: (%d, %d, %d, %d)\n", pointmark(pa),
28097 pointmark(pb), pointmark(pc), pointmark(pd));
28098 printf(
" Second: (%d, %d, %d, %d)\n", pointmark(org(neightet)),
28099 pointmark(dest(neightet)), pointmark(apex(neightet)),
28100 pointmark(oppo(neightet)));
28104 printf(
" !! !! Tet-face has no neighbor (%d, %d, %d) - %d:\n",
28105 pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd));
28109 if (facemarked(tetloop)) {
28111 printf(
" !! tetface (%d, %d, %d) %d is marked.\n", pointmark(pa),
28112 pointmark(pb), pointmark(pc), pointmark(pd));
28116 for (i = 0; i < 6; i++) {
28117 tetloop.ver = edge2ver[i];
28118 if (edgemarked(tetloop)) {
28120 printf(
" !! tetedge (%d, %d) %d, %d is marked.\n",
28121 pointmark(org(tetloop)), pointmark(dest(tetloop)),
28122 pointmark(apex(tetloop)), pointmark(oppo(tetloop)));
28125 tetloop.tet = alltetrahedrontraverse();
28127 if (horrors == 0) {
28129 printf(
" In my studied opinion, the mesh appears to be consistent.\n");
28132 printf(
" !! !! !! !! %d %s witnessed.\n", horrors,
28133 horrors > 1 ?
"abnormity" :
"abnormities");
28144 #pragma GCC diagnostic push 28145 #pragma GCC diagnostic ignored "-Wformat" 28146 int tetgenmesh::checkshells()
28148 triface neightet, symtet;
28149 face shloop, spinsh, nextsh;
28156 printf(
" Checking consistency of the mesh boundary...\n");
28160 void **bakpathblock = subfaces->pathblock;
28161 void *bakpathitem = subfaces->pathitem;
28162 int bakpathitemsleft = subfaces->pathitemsleft;
28163 int bakalignbytes = subfaces->alignbytes;
28165 subfaces->traversalinit();
28166 shloop.sh = shellfacetraverse(subfaces);
28167 while (shloop.sh != NULL) {
28169 for (i = 0; i < 3; i++) {
28172 pb = sdest(shloop);
28174 spivot(spinsh, nextsh);
28175 bakcount = horrors;
28176 while ((nextsh.sh != NULL) && (nextsh.sh != shloop.sh)) {
28177 if (nextsh.sh[3] == NULL) {
28178 printf(
" !! !! Wrong subface-subface connection (Dead subface).\n");
28179 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28180 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28181 pointmark(sapex(spinsh)));
28182 printf(
" Second: x%lx (DEAD)\n", (uintptr_t) nextsh.sh);
28187 if (!(((sorg(nextsh) == pa) && (sdest(nextsh) == pb)) ||
28188 ((sorg(nextsh) == pb) && (sdest(nextsh) == pa)))) {
28189 printf(
" !! !! Wrong subface-subface connection.\n");
28190 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28191 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28192 pointmark(sapex(spinsh)));
28193 printf(
" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh,
28194 pointmark(sorg(nextsh)), pointmark(sdest(nextsh)),
28195 pointmark(sapex(nextsh)));
28200 if (sapex(nextsh) == sapex(spinsh)) {
28201 printf(
" !! !! Existing two duplicated subfaces.\n");
28202 printf(
" First: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28203 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28204 pointmark(sapex(spinsh)));
28205 printf(
" Scond: x%lx (%d, %d, %d).\n", (uintptr_t) nextsh.sh,
28206 pointmark(sorg(nextsh)), pointmark(sdest(nextsh)),
28207 pointmark(sapex(nextsh)));
28212 spivot(spinsh, nextsh);
28215 sspivot(shloop, checkseg);
28216 if (checkseg.sh != NULL) {
28217 if (checkseg.sh[3] == NULL) {
28218 printf(
" !! !! Wrong subface-subseg connection (Dead subseg).\n");
28219 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28220 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28221 pointmark(sapex(shloop)));
28222 printf(
" Sub: x%lx (Dead)\n", (uintptr_t) checkseg.sh);
28225 if (!(((sorg(checkseg) == pa) && (sdest(checkseg) == pb)) ||
28226 ((sorg(checkseg) == pb) && (sdest(checkseg) == pa)))) {
28227 printf(
" !! !! Wrong subface-subseg connection.\n");
28228 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28229 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28230 pointmark(sapex(shloop)));
28231 printf(
" Seg: x%lx (%d, %d).\n", (uintptr_t) checkseg.sh,
28232 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
28237 if (horrors > bakcount)
break;
28238 senextself(shloop);
28241 stpivot(shloop, neightet);
28242 if (neightet.tet != NULL) {
28243 if (neightet.tet[4] == NULL) {
28244 printf(
" !! !! Wrong sub-to-tet connection (Dead tet)\n");
28245 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28246 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28247 pointmark(sapex(shloop)));
28248 printf(
" Tet: x%lx (DEAD)\n", (uintptr_t) neightet.tet);
28251 if (!((sorg(shloop) == org(neightet)) &&
28252 (sdest(shloop) == dest(neightet)))) {
28253 printf(
" !! !! Wrong sub-to-tet connection\n");
28254 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) shloop.sh,
28255 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28256 pointmark(sapex(shloop)));
28257 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28258 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28259 pointmark(dest(neightet)), pointmark(apex(neightet)),
28260 pointmark(oppo(neightet)));
28263 tspivot(neightet, spinsh);
28264 if (!((sorg(spinsh) == org(neightet)) &&
28265 (sdest(spinsh) == dest(neightet)))) {
28266 printf(
" !! !! Wrong tet-sub connection.\n");
28267 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28268 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28269 pointmark(sapex(spinsh)));
28270 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28271 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28272 pointmark(dest(neightet)), pointmark(apex(neightet)),
28273 pointmark(oppo(neightet)));
28276 fsym(neightet, symtet);
28277 tspivot(symtet, spinsh);
28278 if (spinsh.sh != NULL) {
28279 if (!((sorg(spinsh) == org(symtet)) &&
28280 (sdest(spinsh) == dest(symtet)))) {
28281 printf(
" !! !! Wrong tet-sub connection.\n");
28282 printf(
" Sub: x%lx (%d, %d, %d).\n", (uintptr_t) spinsh.sh,
28283 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28284 pointmark(sapex(spinsh)));
28285 printf(
" Tet: x%lx (%d, %d, %d, %d).\n",
28286 (uintptr_t) symtet.tet, pointmark(org(symtet)),
28287 pointmark(dest(symtet)), pointmark(apex(symtet)),
28288 pointmark(oppo(symtet)));
28292 printf(
" Warning: Broken tet-sub-tet connection.\n");
28296 if (sinfected(shloop)) {
28298 printf(
" !! A infected subface: (%d, %d, %d).\n",
28299 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
28300 pointmark(sapex(shloop)));
28302 if (smarktested(shloop)) {
28304 printf(
" !! A marked subface: (%d, %d, %d).\n", pointmark(sorg(shloop)),
28305 pointmark(sdest(shloop)), pointmark(sapex(shloop)));
28307 shloop.sh = shellfacetraverse(subfaces);
28310 if (horrors == 0) {
28312 printf(
" Mesh boundaries connected correctly.\n");
28315 printf(
" !! !! !! !! %d boundary connection viewed with horror.\n",
28319 subfaces->pathblock = bakpathblock;
28320 subfaces->pathitem = bakpathitem;
28321 subfaces->pathitemsleft = bakpathitemsleft;
28322 subfaces->alignbytes = bakalignbytes;
28333 int tetgenmesh::checksegments()
28335 triface tetloop, neightet, spintet;
28337 face neighsh, spinsh, checksh;
28338 face sseg, checkseg;
28346 printf(
" Checking tet->seg connections...\n");
28350 tetrahedrons->traversalinit();
28351 tetloop.tet = tetrahedrontraverse();
28352 while (tetloop.tet != NULL) {
28354 if (tetloop.tet[8] != NULL) {
28355 segs = (shellface *) tetloop.tet[8];
28356 for (i = 0; i < 6; i++) {
28357 sdecode(segs[i], sseg);
28358 if (sseg.sh != NULL) {
28360 tetloop.ver = edge2ver[i];
28362 pa = (point) sseg.sh[3];
28363 pb = (point) sseg.sh[4];
28364 if (!(((org(tetloop) == pa) && (dest(tetloop) == pb)) ||
28365 ((org(tetloop) == pb) && (dest(tetloop) == pa)))) {
28366 printf(
" !! Wrong tet-seg connection.\n");
28367 printf(
" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n",
28368 (uintptr_t) tetloop.tet, pointmark(org(tetloop)),
28369 pointmark(dest(tetloop)), pointmark(apex(tetloop)),
28370 pointmark(oppo(tetloop)), (uintptr_t) sseg.sh,
28371 pointmark(pa), pointmark(pb));
28375 neightet = tetloop;
28377 tsspivot1(neightet, checkseg);
28378 if (checkseg.sh != sseg.sh) {
28379 printf(
" !! Wrong tet->seg connection.\n");
28380 printf(
" Tet: x%lx (%d, %d, %d, %d) - ",
28381 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28382 pointmark(dest(neightet)), pointmark(apex(neightet)),
28383 pointmark(oppo(neightet)));
28384 if (checkseg.sh != NULL) {
28385 printf(
"Seg x%lx (%d, %d).\n", (uintptr_t) checkseg.sh,
28386 pointmark(sorg(checkseg)),pointmark(sdest(checkseg)));
28388 printf(
"Seg: NULL.\n");
28392 fnextself(neightet);
28393 }
while (neightet.tet != tetloop.tet);
28396 sstpivot1(sseg, neightet);
28397 if (neightet.tet == NULL) {
28398 printf(
" !! Wrong seg->tet connection (A NULL tet).\n");
28401 if (!(((org(neightet) == pa) && (dest(neightet) == pb)) ||
28402 ((org(neightet) == pb) && (dest(neightet) == pa)))) {
28403 printf(
" !! Wrong seg->tet connection (Wrong edge).\n");
28404 printf(
" Tet: x%lx (%d, %d, %d, %d) - Seg: x%lx (%d, %d).\n",
28405 (uintptr_t) neightet.tet, pointmark(org(neightet)),
28406 pointmark(dest(neightet)), pointmark(apex(neightet)),
28407 pointmark(oppo(neightet)), (uintptr_t) sseg.sh,
28408 pointmark(pa), pointmark(pb));
28416 neightet.tet = tetloop.tet;
28417 for (i = 0; i < 6; i++) {
28418 neightet.ver = edge2ver[i];
28419 if (edgemarked(neightet)) {
28421 printf(
" !! A marked edge: (%d, %d, %d, %d) -- x%lx %d.\n",
28422 pointmark(org(neightet)), pointmark(dest(neightet)),
28423 pointmark(apex(neightet)), pointmark(oppo(neightet)),
28424 (uintptr_t) neightet.tet, neightet.ver);
28426 spintet = neightet;
28428 fnextself(spintet);
28429 if (!edgemarked(spintet)) {
28430 printf(
" !! !! An unmarked edge (%d, %d, %d, %d) -- x%lx %d.\n",
28431 pointmark(org(spintet)), pointmark(dest(spintet)),
28432 pointmark(apex(spintet)), pointmark(oppo(spintet)),
28433 (uintptr_t) spintet.tet, spintet.ver);
28436 if (spintet.tet == neightet.tet)
break;
28440 tetloop.tet = tetrahedrontraverse();
28444 printf(
" Checking seg->tet connections...\n");
28448 subsegs->traversalinit();
28450 sseg.sh = shellfacetraverse(subsegs);
28451 while (sseg.sh != NULL) {
28454 spivot(sseg, neighsh);
28455 if (neighsh.sh != NULL) {
28459 if (((sorg(spinsh) == pa) && (sdest(spinsh) == pb)) ||
28460 ((sorg(spinsh) == pb) && (sdest(spinsh) == pa))) {
28470 stpivot(spinsh, spintet);
28471 if (spintet.tet != NULL) {
28474 tsspivot1(spintet, checkseg);
28475 if (checkseg.sh == NULL) {
28476 printf(
" !! !! No seg at tet (%d, %d, %d, %d) -- x%lx %d\n",
28477 pointmark(org(spintet)), pointmark(dest(spintet)),
28478 pointmark(apex(spintet)), pointmark(oppo(spintet)),
28479 (uintptr_t) spintet.tet, spintet.ver);
28482 if (checkseg.sh != sseg.sh) {
28483 printf(
" !! !! Wrong seg (%d, %d) at tet (%d, %d, %d, %d)\n",
28484 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)),
28485 pointmark(org(spintet)), pointmark(dest(spintet)),
28486 pointmark(apex(spintet)), pointmark(oppo(spintet)));
28489 fnextself(spintet);
28491 tspivot(spintet, checksh);
28492 if (checksh.sh != NULL)
break;
28496 printf(
" !! Wrong seg-subface (%d, %d, %d) -- x%lx %d connect\n",
28497 pointmark(sorg(spinsh)), pointmark(sdest(spinsh)),
28498 pointmark(sapex(spinsh)), (uintptr_t) spinsh.sh,
28503 spivotself(spinsh);
28504 if (spinsh.sh == NULL)
break;
28505 if (spinsh.sh == neighsh.sh)
break;
28509 sstpivot1(sseg, neightet);
28510 if (neightet.tet == NULL) {
28513 sseg.sh = shellfacetraverse(subsegs);
28517 printf(
" Checking seg->seg connections...\n");
28520 points->traversalinit();
28521 pa = pointtraverse();
28522 while (pa != NULL) {
28523 if (pointtype(pa) == FREESEGVERTEX) {
28526 sdecode(point2sh(pa), sseg);
28527 if ((sseg.sh == NULL) || sseg.sh[3] == NULL) {
28528 printf(
" !! Dead point-to-seg pointer at point %d.\n",
28533 if (sorg(sseg) != pa) {
28534 if (sdest(sseg) != pa) {
28535 printf(
" !! Wrong point-to-seg pointer at point %d.\n",
28540 senext(sseg, checkseg);
28541 if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) {
28542 printf(
" !! Dead seg-seg connection at point %d.\n",
28546 spivotself(checkseg);
28547 checkseg.shver = 0;
28548 if ((sorg(checkseg) != pa) && (sdest(checkseg) != pa)) {
28549 printf(
" !! Wrong seg-seg connection at point %d.\n",
28557 senext2(sseg, checkseg);
28558 if ((checkseg.sh == NULL) || (checkseg.sh[3] == NULL)) {
28559 printf(
" !! Dead seg-seg connection at point %d.\n",
28563 spivotself(checkseg);
28564 checkseg.shver = 0;
28565 if ((sorg(checkseg) != pa) && (sdest(checkseg) != pa)) {
28566 printf(
" !! Wrong seg-seg connection at point %d.\n",
28574 pa = pointtraverse();
28577 if (horrors == 0) {
28578 printf(
" Segments are connected properly.\n");
28580 printf(
" !! !! !! !! Found %d missing connections.\n", horrors);
28582 if (miscount > 0) {
28583 printf(
" !! !! Found %d missing segments.\n", miscount);
28588 #pragma GCC diagnostic pop 28596 int tetgenmesh::checkdelaunay(
int perturb)
28601 point pa, pb, pc, pd, pe;
28607 printf(
" Checking Delaunay property of the mesh...\n");
28614 tetrahedrons->traversalinit();
28615 tetloop.tet = tetrahedrontraverse();
28616 while (tetloop.tet != (tetrahedron *) NULL) {
28618 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28619 fsym(tetloop, symtet);
28622 if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) {
28624 pb = dest(tetloop);
28625 pc = apex(tetloop);
28626 pd = oppo(tetloop);
28629 sign = insphere_s(pa, pb, pc, pd, pe);
28631 sign = insphere(pa, pb, pc, pd, pe);
28635 if (checksubfaceflag) {
28636 tspivot(tetloop, checksh);
28638 if (checksh.sh == NULL) {
28639 printf(
" !! Non-locally Delaunay (%d, %d, %d) - %d, %d\n",
28640 pointmark(pa), pointmark(pb), pointmark(pc), pointmark(pd),
28647 tetloop.tet = tetrahedrontraverse();
28650 if (horrors == 0) {
28653 printf(
" The mesh is constrained Delaunay.\n");
28655 printf(
" The mesh is Delaunay.\n");
28659 printf(
" !! !! !! !! Found %d non-Delaunay faces.\n", horrors);
28677 int tetgenmesh::checkregular(
int type)
28688 printf(
" Checking %s %s property of the mesh...\n",
28689 (type & 2) == 0 ?
"Delaunay" :
"regular",
28690 (type & 1) == 0 ?
" " :
"(s)");
28704 tetrahedrons->traversalinit();
28705 tetloop.tet = tetrahedrontraverse();
28706 while (tetloop.tet != (tetrahedron *) NULL) {
28708 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
28709 fsym(tetloop, symtet);
28712 if (((point) symtet.tet[7] != dummypoint)&&(tetloop.tet < symtet.tet)) {
28713 p[0] = org(tetloop);
28714 p[1] = dest(tetloop);
28715 p[2] = apex(tetloop);
28716 p[3] = oppo(tetloop);
28717 p[4] = oppo(symtet);
28720 sign = insphere(p[1], p[0], p[2], p[3], p[4]);
28721 }
else if (type == 1) {
28722 sign = insphere_s(p[1], p[0], p[2], p[3], p[4]);
28723 }
else if (type == 2) {
28724 sign = orient4d(p[1], p[0], p[2], p[3], p[4],
28725 p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]);
28727 sign = orient4d_s(p[1], p[0], p[2], p[3], p[4],
28728 p[1][3], p[0][3], p[2][3], p[3][3], p[4][3]);
28733 if (checksubfaceflag) {
28734 tspivot(tetloop, checksh);
28736 if (checksh.sh == NULL) {
28737 printf(
" !! Non-locally %s (%d, %d, %d) - %d, %d\n",
28738 (type & 2) == 0 ?
"Delaunay" :
"regular",
28739 pointmark(p[0]), pointmark(p[1]), pointmark(p[2]),
28740 pointmark(p[3]), pointmark(p[4]));
28746 tetloop.tet = tetrahedrontraverse();
28749 if (horrors == 0) {
28752 printf(
" The mesh is constrained %s.\n",
28753 (type & 2) == 0 ?
"Delaunay" :
"regular");
28755 printf(
" The mesh is %s.\n", (type & 2) == 0 ?
"Delaunay" :
"regular");
28759 printf(
" !! !! !! !! Found %d non-%s faces.\n", horrors,
28760 (type & 2) == 0 ?
"Delaunay" :
"regular");
28775 int tetgenmesh::checkconforming(
int flag)
28777 triface searchtet, neightet, spintet;
28780 point eorg, edest, eapex, pa, pb, pc;
28781 REAL cent[3], radius, dist, diff, rd, len;
28783 int encsubsegs, encsubfaces;
28787 REAL A[4][4], rhs[4], D;
28795 printf(
" Checking conforming property of segments...\n");
28800 subsegs->traversalinit();
28801 segloop.sh = shellfacetraverse(subsegs);
28802 while (segloop.sh != (shellface *) NULL) {
28803 eorg = (point) segloop.sh[3];
28804 edest = (point) segloop.sh[4];
28805 radius = 0.5 * distance(eorg, edest);
28806 for (i = 0; i < 3; i++) cent[i] = 0.5 * (eorg[i] + edest[i]);
28809 sstpivot1(segloop, neightet);
28810 if (neightet.tet != NULL) {
28811 spintet = neightet;
28813 eapex= apex(spintet);
28814 if (eapex != dummypoint) {
28815 dist = distance(eapex, cent);
28816 diff = dist - radius;
28817 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28822 fnextself(spintet);
28823 if (spintet.tet == neightet.tet)
break;
28827 printf(
" !! !! Non-conforming segment: (%d, %d)\n",
28828 pointmark(eorg), pointmark(edest));
28831 segloop.sh = shellfacetraverse(subsegs);
28834 if (encsubsegs == 0) {
28836 printf(
" The segments are conforming Delaunay.\n");
28839 printf(
" !! !! %d subsegments are non-conforming.\n", encsubsegs);
28847 printf(
" Checking conforming property of subfaces...\n");
28851 subfaces->traversalinit();
28852 shloop.sh = shellfacetraverse(subfaces);
28853 while (shloop.sh != (shellface *) NULL) {
28854 pa = (point) shloop.sh[3];
28855 pb = (point) shloop.sh[4];
28856 pc = (point) shloop.sh[5];
28859 A[0][0] = pb[0] - pa[0];
28860 A[0][1] = pb[1] - pa[1];
28861 A[0][2] = pb[2] - pa[2];
28862 A[1][0] = pc[0] - pa[0];
28863 A[1][1] = pc[1] - pa[1];
28864 A[1][2] = pc[2] - pa[2];
28865 cross(A[0], A[1], A[2]);
28868 elen[0] = dot(A[0], A[0]);
28869 elen[1] = dot(A[1], A[1]);
28870 rhs[0] = 0.5 * elen[0];
28871 rhs[1] = 0.5 * elen[1];
28874 if (lu_decmp(A, 3, indx, &D, 0)) {
28875 lu_solve(A, 3, indx, rhs, 0);
28876 cent[0] = pa[0] + rhs[0];
28877 cent[1] = pa[1] + rhs[1];
28878 cent[2] = pa[2] + rhs[2];
28879 rd = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28882 for (i = 0; i < 2; i++) {
28883 stpivot(shloop, searchtet);
28884 if (!ishulltet(searchtet)) {
28885 len = distance(oppo(searchtet), cent);
28886 if ((fabs(len - rd) / rd) < b->epsilon) len = rd;
28888 printf(
" !! !! Non-conforming subface: (%d, %d, %d)\n",
28889 pointmark(pa), pointmark(pb), pointmark(pc));
28897 shloop.sh = shellfacetraverse(subfaces);
28900 if (encsubfaces == 0) {
28902 printf(
" The subfaces are conforming Delaunay.\n");
28905 printf(
" !! !! %d subfaces are non-conforming.\n", encsubfaces);
28909 return encsubsegs + encsubfaces;
28918 void tetgenmesh::qualitystatistics()
28920 triface tetloop, neightet;
28923 REAL radiusratiotable[12];
28924 REAL aspectratiotable[12];
28925 REAL A[4][4], rhs[4], D;
28926 REAL V[6][3], N[4][3], H[4];
28927 REAL edgelength[6], alldihed[6], faceangle[3];
28928 REAL shortest, longest;
28929 REAL smallestvolume, biggestvolume;
28930 REAL smallestratio, biggestratio;
28931 REAL smallestradiusratio, biggestradiusratio;
28932 REAL smallestdiangle, biggestdiangle;
28933 REAL smallestfaangle, biggestfaangle;
28934 REAL total_tet_vol, total_tetprism_vol;
28935 REAL tetvol, minaltitude;
28936 REAL cirradius, minheightinv;
28937 REAL shortlen, longlen;
28938 REAL tetaspect, tetradius;
28939 REAL smalldiangle, bigdiangle;
28940 REAL smallfaangle, bigfaangle;
28941 unsigned long radiustable[12];
28942 unsigned long aspecttable[16];
28943 unsigned long dihedangletable[18];
28944 unsigned long faceangletable[18];
28951 triface biggestradiusratiotet;
28953 printf(
"Mesh quality statistics:\n\n");
28955 shortlen = longlen = 0.0;
28956 smalldiangle = bigdiangle = 0.0;
28957 total_tet_vol = 0.0;
28958 total_tetprism_vol = 0.0;
28960 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
28961 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
28962 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
28963 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
28964 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
28965 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
28967 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
28968 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
28969 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
28970 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
28971 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
28972 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
28974 for (i = 0; i < 12; i++) radiustable[i] = 0l;
28975 for (i = 0; i < 12; i++) aspecttable[i] = 0l;
28976 for (i = 0; i < 18; i++) dihedangletable[i] = 0l;
28977 for (i = 0; i < 18; i++) faceangletable[i] = 0l;
28979 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
28980 minaltitude = minaltitude * minaltitude;
28981 shortest = minaltitude;
28983 smallestvolume = minaltitude;
28984 biggestvolume = 0.0;
28985 smallestratio = smallestradiusratio = 1e+16;
28986 biggestratio = biggestradiusratio = 0.0;
28987 smallestdiangle = smallestfaangle = 180.0;
28988 biggestdiangle = biggestfaangle = 0.0;
28991 int attrnum = numelemattrib - 1;
28994 tetrahedrons->traversalinit();
28995 tetloop.tet = tetrahedrontraverse();
28996 while (tetloop.tet != (tetrahedron *) NULL) {
29000 if (elemattribute(tetloop.tet, attrnum) == -1.0) {
29001 tetloop.tet = tetrahedrontraverse();
29007 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
29010 tetvol = orient3dfast(p[1], p[0], p[2], p[3]) / 6.0;
29011 total_tet_vol += tetvol;
29012 total_tetprism_vol += tetprismvol(p[0], p[1], p[2], p[3]);
29015 if (tetvol < smallestvolume) {
29016 smallestvolume = tetvol;
29018 if (tetvol > biggestvolume) {
29019 biggestvolume = tetvol;
29023 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
29024 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
29025 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
29026 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
29027 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
29028 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
29031 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
29034 for (i = 0; i < 6; i++) {
29036 shortlen = longlen = edgelength[i];
29038 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
29039 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
29041 if (edgelength[i] > longest) {
29042 longest = edgelength[i];
29044 if (edgelength[i] < shortest) {
29045 shortest = edgelength[i];
29050 for (j = 0; j < 3; j++) {
29051 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
29055 if (lu_decmp(A, 3, indx, &D, 0)) {
29057 for (j = 0; j < 3; j++) {
29058 for (i = 0; i < 3; i++) rhs[i] = 0.0;
29060 lu_solve(A, 3, indx, rhs, 0);
29061 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
29064 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
29066 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
29067 lu_solve(A, 3, indx, rhs, 0);
29068 cirradius = sqrt(dot(rhs, rhs));
29070 for (i = 0; i < 4; i++) {
29072 H[i] = sqrt(dot(N[i], N[i]));
29073 for (j = 0; j < 3; j++) N[i][j] /= H[i];
29078 minheightinv = H[0];
29079 for (i = 1; i < 4; i++) {
29080 if (H[i] > minheightinv) minheightinv = H[i];
29084 if (tetvol <= 0.0) {
29085 printf(
" !! Warning: A %s tet (%d,%d,%d,%d).\n",
29086 tetvol < 0 ?
"inverted" :
"degenerated", pointmark(p[0]),
29087 pointmark(p[1]), pointmark(p[2]), pointmark(p[3]));
29089 tetloop.tet = tetrahedrontraverse();
29093 facenormal(p[2], p[1], p[3], N[0], 1, NULL);
29094 facenormal(p[0], p[2], p[3], N[1], 1, NULL);
29095 facenormal(p[1], p[0], p[3], N[2], 1, NULL);
29096 facenormal(p[0], p[1], p[2], N[3], 1, NULL);
29098 for (i = 0; i < 4; i++) {
29100 H[i] = sqrt(dot(N[i], N[i]));
29101 for (j = 0; j < 3; j++) N[i][j] /= H[i];
29104 minheightinv = (H[0] / tetvol);
29105 for (i = 1; i < 4; i++) {
29106 if ((H[i] / tetvol) > minheightinv) minheightinv = (H[i] / tetvol);
29109 cirradius = 0.5 * sqrt(longlen);
29114 for (i = 1; i < 4; i++) {
29115 alldihed[j] = -dot(N[0], N[i]);
29116 if (alldihed[j] < -1.0) alldihed[j] = -1;
29117 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29118 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29121 for (i = 2; i < 4; i++) {
29122 alldihed[j] = -dot(N[1], N[i]);
29123 if (alldihed[j] < -1.0) alldihed[j] = -1;
29124 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29125 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29128 alldihed[j] = -dot(N[2], N[3]);
29129 if (alldihed[j] < -1.0) alldihed[j] = -1;
29130 else if (alldihed[j] > 1.0) alldihed[j] = 1;
29131 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
29134 for (i = 0; i < 6; i++) {
29136 smalldiangle = bigdiangle = alldihed[i];
29138 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
29139 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
29141 if (alldihed[i] < smallestdiangle) {
29142 smallestdiangle = alldihed[i];
29144 if (alldihed[i] > biggestdiangle) {
29145 biggestdiangle = alldihed[i];
29148 if (alldihed[i] < 5.0) {
29150 }
else if (alldihed[i] >= 5.0 && alldihed[i] < 10.0) {
29152 }
else if (alldihed[i] >= 80.0 && alldihed[i] < 110.0) {
29154 }
else if (alldihed[i] >= 170.0 && alldihed[i] < 175.0) {
29156 }
else if (alldihed[i] >= 175.0) {
29159 tendegree = (int) (alldihed[i] / 10.);
29160 if (alldihed[i] < 80.0) {
29166 dihedangletable[tendegree]++;
29172 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
29173 fsym(tetloop, neightet);
29175 if (((point) neightet.tet[7] == dummypoint) ||
29176 (tetloop.tet < neightet.tet)) {
29177 p[0] = org(tetloop);
29178 p[1] = dest(tetloop);
29179 p[2] = apex(tetloop);
29180 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
29181 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
29182 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
29184 for (i = 0; i < 3; i++) {
29185 faceangle[i] = (faceangle[i] * 180.0) / PI;
29188 for (i = 0; i < 3; i++) {
29190 smallfaangle = bigfaangle = faceangle[i];
29192 smallfaangle = faceangle[i] < smallfaangle ?
29193 faceangle[i] : smallfaangle;
29194 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
29196 if (faceangle[i] < smallestfaangle) {
29197 smallestfaangle = faceangle[i];
29199 if (faceangle[i] > biggestfaangle) {
29200 biggestfaangle = faceangle[i];
29202 tendegree = (int) (faceangle[i] / 10.);
29203 faceangletable[tendegree]++;
29209 tetradius = cirradius / sqrt(shortlen);
29210 if (tetradius < smallestradiusratio) {
29211 smallestradiusratio = tetradius;
29213 if (tetradius > biggestradiusratio) {
29214 biggestradiusratio = tetradius;
29215 biggestradiusratiotet.tet = tetloop.tet;
29218 tetaspect = sqrt(longlen) * minheightinv;
29220 if (tetaspect < smallestratio) {
29221 smallestratio = tetaspect;
29223 if (tetaspect > biggestratio) {
29224 biggestratio = tetaspect;
29228 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
29231 aspecttable[aspectindex]++;
29233 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
29236 radiustable[radiusindex]++;
29238 tetloop.tet = tetrahedrontraverse();
29241 shortest = sqrt(shortest);
29242 longest = sqrt(longest);
29243 minaltitude = sqrt(minaltitude);
29245 printf(
" Smallest volume: %16.5g | Largest volume: %16.5g\n",
29246 smallestvolume, biggestvolume);
29247 printf(
" Shortest edge: %16.5g | Longest edge: %16.5g\n",
29248 shortest, longest);
29249 printf(
" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
29250 smallestratio, biggestratio);
29251 sprintf(sbuf,
"%.17g", biggestfaangle);
29252 if (strlen(sbuf) > 8) {
29255 printf(
" Smallest facangle: %14.5g | Largest facangle: %s\n",
29256 smallestfaangle, sbuf);
29257 sprintf(sbuf,
"%.17g", biggestdiangle);
29258 if (strlen(sbuf) > 8) {
29261 printf(
" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
29262 smallestdiangle, sbuf);
29264 printf(
" Aspect ratio histogram:\n");
29265 printf(
" < %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n",
29266 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
29267 aspectratiotable[6], aspecttable[6]);
29268 for (i = 1; i < 5; i++) {
29269 printf(
" %6.6g - %-6.6g : %8ld | %6.6g - %-6.6g : %8ld\n",
29270 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
29271 aspectratiotable[i + 5], aspectratiotable[i + 6],
29272 aspecttable[i + 6]);
29274 printf(
" %6.6g - %-6.6g : %8ld | %6.6g - : %8ld\n",
29275 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
29276 aspectratiotable[10], aspecttable[11]);
29277 printf(
" (A tetrahedron's aspect ratio is its longest edge length");
29278 printf(
" divided by its\n");
29279 printf(
" smallest side height)\n\n");
29281 printf(
" Face angle histogram:\n");
29282 for (i = 0; i < 9; i++) {
29283 printf(
" %3d - %3d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29284 i * 10, i * 10 + 10, faceangletable[i],
29285 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
29287 if (minfaceang != PI) {
29288 printf(
" Minimum input face angle is %g (degree).\n",
29289 minfaceang / PI * 180.0);
29293 printf(
" Dihedral angle histogram:\n");
29295 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29296 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
29297 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29298 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
29300 for (i = 2; i < 7; i++) {
29301 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29302 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
29303 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
29306 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29307 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
29308 printf(
" %3d - %2d degrees: %8ld | %3d - %3d degrees: %8ld\n",
29309 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
29310 if (minfacetdihed != PI) {
29311 printf(
" Minimum input dihedral angle is %g (degree).\n",
29312 minfacetdihed / PI * 180.0);
29326 void tetgenmesh::memorystatistics()
29328 printf(
"Memory usage statistics:\n\n");
29332 tetrahedrons->pathblock = tetrahedrons->firstblock;
29333 while (tetrahedrons->pathblock != NULL) {
29335 tetrahedrons->pathblock = (
void **) *(tetrahedrons->pathblock);
29339 unsigned long totalmeshmemory = 0l, totalt2shmemory = 0l;
29340 totalmeshmemory = points->maxitems * points->itembytes +
29341 tetrahedrons->maxitems * tetrahedrons->itembytes;
29342 if (b->plc || b->refine) {
29343 totalmeshmemory += (subfaces->maxitems * subfaces->itembytes +
29344 subsegs->maxitems * subsegs->itembytes);
29345 totalt2shmemory = (tet2subpool->maxitems * tet2subpool->itembytes +
29346 tet2segpool->maxitems * tet2segpool->itembytes);
29349 unsigned long totalalgomemory = 0l;
29350 totalalgomemory = cavetetlist->totalmemory + cavebdrylist->totalmemory +
29351 caveoldtetlist->totalmemory +
29352 flippool->maxitems * flippool->itembytes;
29353 if (b->plc || b->refine) {
29354 totalalgomemory += (subsegstack->totalmemory + subfacstack->totalmemory +
29355 subvertstack->totalmemory +
29356 caveshlist->totalmemory + caveshbdlist->totalmemory +
29357 cavesegshlist->totalmemory +
29358 cavetetshlist->totalmemory +
29359 cavetetseglist->totalmemory +
29360 caveencshlist->totalmemory +
29361 caveencseglist->totalmemory +
29362 cavetetvertlist->totalmemory +
29363 unflipqueue->totalmemory);
29366 printf(
" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
29367 printf(
" Maximum number of tet blocks (blocksize = %d): %d\n",
29368 b->tetrahedraperblock, tetblocks);
29388 if (b->plc || b->refine) {
29389 printf(
" Approximate memory for tetrahedral mesh (bytes): ");
29390 printfcomma(totalmeshmemory); printf(
"\n");
29392 printf(
" Approximate memory for extra pointers (bytes): ");
29393 printfcomma(totalt2shmemory); printf(
"\n");
29395 printf(
" Approximate memory for tetrahedralization (bytes): ");
29396 printfcomma(totalmeshmemory); printf(
"\n");
29398 printf(
" Approximate memory for algorithms (bytes): ");
29399 printfcomma(totalalgomemory); printf(
"\n");
29400 printf(
" Approximate memory for working arrays (bytes): ");
29401 printfcomma(totalworkmemory); printf(
"\n");
29402 printf(
" Approximate total used memory (bytes): ");
29403 printfcomma(totalmeshmemory + totalt2shmemory + totalalgomemory +
29416 void tetgenmesh::statistics()
29418 long tetnumber, facenumber;
29420 printf(
"\nStatistics:\n\n");
29421 printf(
" Input points: %d\n", in->numberofpoints);
29423 printf(
" Input tetrahedra: %d\n", in->numberoftetrahedra);
29424 if (in->numberoftrifaces > 0) {
29425 printf(
" Input triangles: %d\n", in->numberoftrifaces);
29427 if (in->numberofedges > 0) {
29428 printf(
" Input edges: %d\n", in->numberofedges);
29430 }
else if (b->plc) {
29431 printf(
" Input facets: %d\n", in->numberoffacets);
29432 printf(
" Input segments: %ld\n", insegments);
29433 if (in->numberofedges > 0) {
29434 printf(
" Input edges: %d\n", in->numberofedges);
29436 printf(
" Input holes: %d\n", in->numberofholes);
29437 printf(
" Input regions: %d\n", in->numberofregions);
29440 tetnumber = tetrahedrons->items - hullsize;
29441 facenumber = (tetnumber * 4l + hullsize) / 2l;
29444 printf(
"\n Mesh points: %ld\n", points->items - nonregularcount);
29446 printf(
"\n Mesh points: %ld\n", points->items);
29448 printf(
" Mesh tetrahedra: %ld\n", tetnumber);
29449 printf(
" Mesh faces: %ld\n", facenumber);
29450 if (meshedges > 0l) {
29451 printf(
" Mesh edges: %ld\n", meshedges);
29454 long vsize = points->items - dupverts - unuverts;
29455 if (b->weighted) vsize -= nonregularcount;
29456 meshedges = vsize + facenumber - tetnumber - 1;
29457 printf(
" Mesh edges: %ld\n", meshedges);
29461 if (b->plc || b->refine) {
29462 printf(
" Mesh faces on exterior boundary: %ld\n", hullsize);
29463 if (meshhulledges > 0l) {
29464 printf(
" Mesh edges on exterior boundary: %ld\n", meshhulledges);
29466 printf(
" Mesh faces on input facets: %ld\n", subfaces->items);
29467 printf(
" Mesh edges on input segments: %ld\n", subsegs->items);
29468 if (st_facref_count > 0l) {
29469 printf(
" Steiner points on input facets: %ld\n", st_facref_count);
29471 if (st_segref_count > 0l) {
29472 printf(
" Steiner points on input segments: %ld\n", st_segref_count);
29474 if (st_volref_count > 0l) {
29475 printf(
" Steiner points inside domain: %ld\n", st_volref_count);
29478 printf(
" Convex hull faces: %ld\n", hullsize);
29479 if (meshhulledges > 0l) {
29480 printf(
" Convex hull edges: %ld\n", meshhulledges);
29484 printf(
" Skipped non-regular points: %ld\n", nonregularcount);
29489 if (b->verbose > 0) {
29490 if (b->plc || b->refine) {
29491 if (tetrahedrons->items > 0l) {
29492 qualitystatistics();
29495 if (tetrahedrons->items > 0l) {
29496 memorystatistics();
29521 void tetgenmesh::jettisonnodes()
29525 int oldidx, newidx;
29529 printf(
"Jettisoning redundant points.\n");
29532 points->traversalinit();
29533 pointloop = pointtraverse();
29534 oldidx = newidx = 0;
29536 while (pointloop != (point) NULL) {
29537 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
29538 (pointtype(pointloop) == UNUSEDVERTEX);
29541 pointdealloc(pointloop);
29545 setpointmark(pointloop, newidx + in->firstnumber);
29546 if (in->pointmarkerlist != (
int *) NULL) {
29547 if (oldidx < in->numberofpoints) {
29549 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
29555 pointloop = pointtraverse();
29558 printf(
" %ld duplicated vertices are removed.\n", dupverts);
29559 printf(
" %ld unused vertices are removed.\n", unuverts);
29567 points->deaditemstack = (
void *) NULL;
29580 void tetgenmesh::highorder()
29582 triface tetloop, worktet, spintet;
29583 point *extralist, *adjextralist;
29584 point torg, tdest, newpoint;
29585 int highorderindex;
29590 printf(
"Adding vertices for second-order tetrahedra.\n");
29594 highordertable =
new point[tetrahedrons->items * 6];
29595 if (highordertable == (point *) NULL) {
29596 terminatetetgen(
this, 1);
29600 highorderindex = 11;
29607 points->deaditemstack = (
void *) NULL;
29612 tetrahedrons->traversalinit();
29613 tetloop.tet = tetrahedrontraverse();
29614 while (tetloop.tet != (tetrahedron *) NULL) {
29615 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
29616 for (j = 0; j < 6; j++) {
29617 highordertable[i + j] = (point) NULL;
29620 tetloop.tet = tetrahedrontraverse();
29628 tetrahedrons->traversalinit();
29629 tetloop.tet = tetrahedrontraverse();
29630 while (tetloop.tet != (tetrahedron *) NULL) {
29632 extralist = (point *) tetloop.tet[highorderindex];
29633 worktet.tet = tetloop.tet;
29634 for (i = 0; i < 6; i++) {
29635 if (extralist[i] == (point) NULL) {
29637 worktet.ver = edge2ver[i];
29639 torg = org(worktet);
29640 tdest = dest(worktet);
29641 makepoint(&newpoint, FREEVOLVERTEX);
29642 for (j = 0; j < 3 + numpointattrib; j++) {
29643 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
29646 for (j = 0; j < in->numberofpointmtrs; j++) {
29647 newpoint[pointmtrindex + j] =
29648 0.5 * (torg[pointmtrindex + j] + tdest[pointmtrindex + j]);
29653 if (!ishulltet(spintet)) {
29654 adjextralist = (point *) spintet.tet[highorderindex];
29655 adjextralist[ver2edge[spintet.ver]] = newpoint;
29657 fnextself(spintet);
29658 if (spintet.tet == worktet.tet)
break;
29662 tetloop.tet = tetrahedrontraverse();
29675 void tetgenmesh::indexelements()
29678 int eindex = b->zeroindex ? 0 : in->firstnumber;
29679 tetrahedrons->traversalinit();
29680 worktet.tet = tetrahedrontraverse();
29681 while (worktet.tet != NULL) {
29682 setelemindex(worktet.tet, eindex);
29687 tetrahedron tptr = encode(worktet);
29688 for (
int i = 0; i < 4; i++) {
29689 setpoint2tet((point) (worktet.tet[4 + i]), tptr);
29692 worktet.tet = tetrahedrontraverse();
29708 void tetgenmesh::numberedges()
29710 triface worktet, spintet;
29715 meshedges = meshhulledges = 0l;
29717 tetrahedrons->traversalinit();
29718 worktet.tet = tetrahedrontraverse();
29719 while (worktet.tet != NULL) {
29720 for (i = 0; i < 6; i++) {
29721 worktet.ver = edge2ver[i];
29723 fnext(worktet, spintet);
29725 if (!ishulltet(spintet)) {
29726 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
29730 fnextself(spintet);
29731 }
while (spintet.tet != worktet.tet);
29732 if (spintet.tet == worktet.tet) {
29734 if (ishulledge) meshhulledges++;
29738 worktet.tet = tetrahedrontraverse();
29751 void tetgenmesh::outnodes(
tetgenio* out)
29753 FILE *outfile = NULL;
29754 char outnodefilename[FILENAMESIZE];
29757 int nextras, bmark, marker = 0, weightDT = 0;
29758 int coordindex, attribindex;
29759 int pointnumber, firstindex;
29763 strcpy(outnodefilename, b->outfilename);
29764 strcat(outnodefilename,
".node");
29769 printf(
"Writing %s.\n", outnodefilename);
29771 printf(
"Writing nodes.\n");
29775 nextras = numpointattrib;
29777 if (b->weighted_param == 0) weightDT = 1;
29780 bmark = !b->nobound && in->pointmarkerlist;
29783 outfile = fopen(outnodefilename,
"w");
29784 if (outfile == (FILE *) NULL) {
29785 printf(
"File I/O Error: Cannot create file %s.\n", outnodefilename);
29786 terminatetetgen(
this, 1);
29790 fprintf(outfile,
"%ld %d %d %d\n", points->items, 3, nextras, bmark);
29793 out->pointlist =
new REAL[points->items * 3];
29794 if (out->pointlist == (REAL *) NULL) {
29795 printf(
"Error: Out of memory.\n");
29796 terminatetetgen(
this, 1);
29800 out->pointattributelist =
new REAL[points->items * nextras];
29801 if (out->pointattributelist == (REAL *) NULL) {
29802 printf(
"Error: Out of memory.\n");
29803 terminatetetgen(
this, 1);
29808 out->pointmarkerlist =
new int[points->items];
29809 if (out->pointmarkerlist == (
int *) NULL) {
29810 printf(
"Error: Out of memory.\n");
29811 terminatetetgen(
this, 1);
29816 if (out->pointparamlist == NULL) {
29817 printf(
"Error: Out of memory.\n");
29818 terminatetetgen(
this, 1);
29821 out->numberofpoints = points->items;
29822 out->numberofpointattributes = nextras;
29828 firstindex = b->zeroindex ? 0 : in->firstnumber;
29830 points->traversalinit();
29831 pointloop = pointtraverse();
29832 pointnumber = firstindex;
29834 while (pointloop != (point) NULL) {
29839 if (index < in->numberofpoints) {
29841 marker = in->pointmarkerlist[index];
29843 if ((pointtype(pointloop) == FREESEGVERTEX) ||
29844 (pointtype(pointloop) == FREEFACETVERTEX)) {
29845 sdecode(point2sh(pointloop), parentsh);
29846 if (parentsh.sh != NULL) {
29847 marker = shellmark(parentsh);
29854 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
29855 pointloop[0], pointloop[1], pointloop[2]);
29856 for (i = 0; i < nextras; i++) {
29858 if ((i == 0) && weightDT) {
29859 fprintf(outfile,
" %.17g", pointloop[0] * pointloop[0] +
29860 pointloop[1] * pointloop[1] + pointloop[2] * pointloop[2]
29861 - pointloop[3 + i]);
29863 fprintf(outfile,
" %.17g", pointloop[3 + i]);
29868 fprintf(outfile,
" %d", marker);
29871 fprintf(outfile,
" %.8g %.8g %d", pointgeomuv(pointloop, 0),
29872 pointgeomuv(pointloop, 1), pointgeomtag(pointloop));
29873 if (pointtype(pointloop) == RIDGEVERTEX) {
29874 fprintf(outfile,
" 0");
29875 }
else if (pointtype(pointloop) == ACUTEVERTEX) {
29876 fprintf(outfile,
" 0");
29877 }
else if (pointtype(pointloop) == FREESEGVERTEX) {
29878 fprintf(outfile,
" 1");
29879 }
else if (pointtype(pointloop) == FREEFACETVERTEX) {
29880 fprintf(outfile,
" 2");
29881 }
else if (pointtype(pointloop) == FREEVOLVERTEX) {
29882 fprintf(outfile,
" 3");
29884 fprintf(outfile,
" -1");
29887 fprintf(outfile,
"\n");
29890 out->pointlist[coordindex++] = pointloop[0];
29891 out->pointlist[coordindex++] = pointloop[1];
29892 out->pointlist[coordindex++] = pointloop[2];
29894 for (i = 0; i < nextras; i++) {
29896 if ((i == 0) && weightDT) {
29897 out->pointattributelist[attribindex++] =
29898 pointloop[0] * pointloop[0] + pointloop[1] * pointloop[1] +
29899 pointloop[2] * pointloop[2] - pointloop[3 + i];
29901 out->pointattributelist[attribindex++] = pointloop[3 + i];
29906 out->pointmarkerlist[index] = marker;
29909 out->pointparamlist[index].uv[0] = pointgeomuv(pointloop, 0);
29910 out->pointparamlist[index].uv[1] = pointgeomuv(pointloop, 1);
29911 out->pointparamlist[index].tag = pointgeomtag(pointloop);
29912 if (pointtype(pointloop) == RIDGEVERTEX) {
29913 out->pointparamlist[index].type = 0;
29914 }
else if (pointtype(pointloop) == ACUTEVERTEX) {
29915 out->pointparamlist[index].type = 0;
29916 }
else if (pointtype(pointloop) == FREESEGVERTEX) {
29917 out->pointparamlist[index].type = 1;
29918 }
else if (pointtype(pointloop) == FREEFACETVERTEX) {
29919 out->pointparamlist[index].type = 2;
29920 }
else if (pointtype(pointloop) == FREEVOLVERTEX) {
29921 out->pointparamlist[index].type = 3;
29923 out->pointparamlist[index].type = -1;
29927 pointloop = pointtraverse();
29933 fprintf(outfile,
"# Generated by %s\n", b->commandline);
29944 void tetgenmesh::outmetrics(
tetgenio* out)
29946 FILE *outfile = NULL;
29947 char outmtrfilename[FILENAMESIZE];
29951 int msize = (sizeoftensor - useinsertradius);
29957 strcpy(outmtrfilename, b->outfilename);
29958 strcat(outmtrfilename,
".mtr");
29963 printf(
"Writing %s.\n", outmtrfilename);
29965 printf(
"Writing metrics.\n");
29970 outfile = fopen(outmtrfilename,
"w");
29971 if (outfile == (FILE *) NULL) {
29972 printf(
"File I/O Error: Cannot create file %s.\n", outmtrfilename);
29973 terminatetetgen(
this, 3);
29976 fprintf(outfile,
"%ld %d\n", points->items, msize);
29979 out->numberofpointmtrs = msize;
29980 out->pointmtrlist =
new REAL[points->items * msize];
29981 if (out->pointmtrlist == (REAL *) NULL) {
29982 terminatetetgen(
this, 1);
29986 points->traversalinit();
29987 ptloop = pointtraverse();
29988 while (ptloop != (point) NULL) {
29990 for (i = 0; i < msize; i++) {
29991 fprintf(outfile,
" %-16.8e", ptloop[pointmtrindex + i]);
29993 fprintf(outfile,
"\n");
29995 for (i = 0; i < msize; i++) {
29996 out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
29999 ptloop = pointtraverse();
30004 strcpy(outmtrfilename, b->outfilename);
30005 strcat(outmtrfilename,
".p2t");
30010 printf(
"Writing %s.\n", outmtrfilename);
30012 printf(
"Writing point-to-tet map.\n");
30017 outfile = fopen(outmtrfilename,
"w");
30018 if (outfile == (FILE *) NULL) {
30019 printf(
"File I/O Error: Cannot create file %s.\n", outmtrfilename);
30020 terminatetetgen(
this, 3);
30026 out->point2tetlist =
new int[points->items];
30027 if (out->point2tetlist == (
int *) NULL) {
30028 terminatetetgen(
this, 1);
30034 bgm->indexelements();
30037 int firstindex = b->zeroindex ? 0 : in->firstnumber;
30038 int pointindex = firstindex;
30042 points->traversalinit();
30043 ptloop = pointtraverse();
30044 while (ptloop != (point) NULL) {
30046 bgm->decode(point2bgmtet(ptloop), parenttet);
30048 decode(point2tet(ptloop), parenttet);
30051 fprintf(outfile,
"%d %d\n", pointindex, elemindex(parenttet.tet));
30053 out->point2tetlist[i] = elemindex(parenttet.tet);
30057 ptloop = pointtraverse();
30061 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30076 void tetgenmesh::outelements(
tetgenio* out)
30078 FILE *outfile = NULL;
30079 char outelefilename[FILENAMESIZE];
30081 point p1, p2, p3, p4;
30083 REAL *talist = NULL;
30086 int firstindex, shift;
30087 int pointindex, attribindex;
30088 int highorderindex = 11;
30094 strcpy(outelefilename, b->outfilename);
30095 strcat(outelefilename,
".ele");
30100 printf(
"Writing %s.\n", outelefilename);
30102 printf(
"Writing elements.\n");
30107 ntets = tetrahedrons->items - hullsize;
30109 eextras = numelemattrib;
30111 outfile = fopen(outelefilename,
"w");
30112 if (outfile == (FILE *) NULL) {
30113 printf(
"File I/O Error: Cannot create file %s.\n", outelefilename);
30114 terminatetetgen(
this, 1);
30117 fprintf(outfile,
"%ld %d %d\n", ntets, b->order == 1 ? 4 : 10, eextras);
30120 out->tetrahedronlist =
new int[ntets * (b->order == 1 ? 4 : 10)];
30121 if (out->tetrahedronlist == (
int *) NULL) {
30122 printf(
"Error: Out of memory.\n");
30123 terminatetetgen(
this, 1);
30127 out->tetrahedronattributelist =
new REAL[ntets * eextras];
30128 if (out->tetrahedronattributelist == (REAL *) NULL) {
30129 printf(
"Error: Out of memory.\n");
30130 terminatetetgen(
this, 1);
30133 out->numberoftetrahedra = ntets;
30134 out->numberofcorners = b->order == 1 ? 4 : 10;
30135 out->numberoftetrahedronattributes = eextras;
30136 tlist = out->tetrahedronlist;
30137 talist = out->tetrahedronattributelist;
30143 firstindex = b->zeroindex ? 0 : in->firstnumber;
30145 if ((in->firstnumber == 1) && (firstindex == 0)) {
30149 tetrahedrons->traversalinit();
30150 tptr = tetrahedrontraverse();
30151 elementnumber = firstindex;
30152 while (tptr != (tetrahedron *) NULL) {
30153 if (!b->reversetetori) {
30154 p1 = (point) tptr[4];
30155 p2 = (point) tptr[5];
30157 p1 = (point) tptr[5];
30158 p2 = (point) tptr[4];
30160 p3 = (point) tptr[6];
30161 p4 = (point) tptr[7];
30164 fprintf(outfile,
"%5d %5d %5d %5d %5d", elementnumber,
30165 pointmark(p1) - shift, pointmark(p2) - shift,
30166 pointmark(p3) - shift, pointmark(p4) - shift);
30167 if (b->order == 2) {
30168 extralist = (point *) tptr[highorderindex];
30170 fprintf(outfile,
" %5d %5d %5d %5d %5d %5d",
30171 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
30172 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
30173 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
30175 for (i = 0; i < eextras; i++) {
30176 fprintf(outfile,
" %.17g", elemattribute(tptr, i));
30178 fprintf(outfile,
"\n");
30180 tlist[pointindex++] = pointmark(p1) - shift;
30181 tlist[pointindex++] = pointmark(p2) - shift;
30182 tlist[pointindex++] = pointmark(p3) - shift;
30183 tlist[pointindex++] = pointmark(p4) - shift;
30184 if (b->order == 2) {
30185 extralist = (point *) tptr[highorderindex];
30186 tlist[pointindex++] = pointmark(extralist[0]) - shift;
30187 tlist[pointindex++] = pointmark(extralist[1]) - shift;
30188 tlist[pointindex++] = pointmark(extralist[2]) - shift;
30189 tlist[pointindex++] = pointmark(extralist[3]) - shift;
30190 tlist[pointindex++] = pointmark(extralist[4]) - shift;
30191 tlist[pointindex++] = pointmark(extralist[5]) - shift;
30193 for (i = 0; i < eextras; i++) {
30194 talist[attribindex++] = elemattribute(tptr, i);
30198 setelemindex(tptr, elementnumber);
30202 for (
int i = 0; i < 4; i++) {
30203 setpoint2tet((point) (tptr[4 + i]), (tetrahedron) tptr);
30206 tptr = tetrahedrontraverse();
30212 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30223 void tetgenmesh::outfaces(
tetgenio* out)
30225 FILE *outfile = NULL;
30226 char facefilename[FILENAMESIZE];
30227 triface tface, tsymface;
30229 point torg, tdest, tapex;
30231 int *elist = NULL, *emlist = NULL;
30232 int neigh1 = 0, neigh2 = 0;
30234 int firstindex, shift;
30240 point *extralist, pp[3] = {0,0,0};
30241 int highorderindex = 11;
30242 int o2index = 0, i;
30245 int *tet2facelist = NULL;
30249 strcpy(facefilename, b->outfilename);
30250 strcat(facefilename,
".face");
30255 printf(
"Writing %s.\n", facefilename);
30257 printf(
"Writing faces.\n");
30261 ntets = tetrahedrons->items - hullsize;
30262 faces = (ntets * 4l + hullsize) / 2l;
30265 outfile = fopen(facefilename,
"w");
30266 if (outfile == (FILE *) NULL) {
30267 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30268 terminatetetgen(
this, 1);
30270 fprintf(outfile,
"%ld %d\n", faces, !b->nobound);
30273 out->trifacelist =
new int[faces * 3];
30274 if (out->trifacelist == (
int *) NULL) {
30275 printf(
"Error: Out of memory.\n");
30276 terminatetetgen(
this, 1);
30278 if (b->order == 2) {
30279 out->o2facelist =
new int[faces * 3];
30283 out->trifacemarkerlist =
new int[faces];
30284 if (out->trifacemarkerlist == (
int *) NULL) {
30285 printf(
"Error: Out of memory.\n");
30286 terminatetetgen(
this, 1);
30289 if (b->neighout > 1) {
30291 out->face2tetlist =
new int[faces * 2];
30292 if (out->face2tetlist == (
int *) NULL) {
30293 printf(
"Error: Out of memory.\n");
30294 terminatetetgen(
this, 1);
30297 out->numberoftrifaces = faces;
30298 elist = out->trifacelist;
30299 emlist = out->trifacemarkerlist;
30302 if (b->neighout > 1) {
30304 tet2facelist =
new int[ntets * 4];
30308 firstindex = b->zeroindex ? 0 : in->firstnumber;
30310 if ((in->firstnumber == 1) && (firstindex == 0)) {
30314 tetrahedrons->traversalinit();
30315 tface.tet = tetrahedrontraverse();
30316 facenumber = firstindex;
30321 while (tface.tet != (tetrahedron *) NULL) {
30322 for (tface.ver = 0; tface.ver < 4; tface.ver ++) {
30323 fsym(tface, tsymface);
30324 if (ishulltet(tsymface) ||
30325 (elemindex(tface.tet) < elemindex(tsymface.tet))) {
30327 tdest = dest(tface);
30328 tapex = apex(tface);
30329 if (b->order == 2) {
30331 extralist = (point *) (tface.tet[highorderindex]);
30333 enext(tface, workface);
30334 for (i = 0; i < 3; i++) {
30335 pp[i] = extralist[ver2edge[workface.ver]];
30336 enextself(workface);
30341 if (b->plc || b->refine) {
30343 tspivot(tface, checkmark);
30344 if (checkmark.sh == NULL) {
30347 marker = shellmark(checkmark);
30351 marker = (int) ishulltet(tsymface);
30354 if (b->neighout > 1) {
30356 if (!ishulltet(tface)) {
30357 neigh1 = elemindex(tface.tet);
30361 if (!ishulltet(tsymface)) {
30362 neigh2 = elemindex(tsymface.tet);
30367 tidx = elemindex(tface.tet) - firstindex;
30368 tet2facelist[tidx * 4 + tface.ver] = facenumber;
30369 if (!ishulltet(tsymface)) {
30370 tidx = elemindex(tsymface.tet) - firstindex;
30371 tet2facelist[tidx * 4 + (tsymface.ver & 3)] = facenumber;
30376 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30377 pointmark(torg) - shift, pointmark(tdest) - shift,
30378 pointmark(tapex) - shift);
30379 if (b->order == 2) {
30380 fprintf(outfile,
" %4d %4d %4d", pointmark(pp[0]) - shift,
30381 pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
30385 fprintf(outfile,
" %d", marker);
30387 if (b->neighout > 1) {
30388 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
30390 fprintf(outfile,
"\n");
30393 elist[index++] = pointmark(torg) - shift;
30394 elist[index++] = pointmark(tdest) - shift;
30395 elist[index++] = pointmark(tapex) - shift;
30396 if (b->order == 2) {
30397 out->o2facelist[o2index++] = pointmark(pp[0]) - shift;
30398 out->o2facelist[o2index++] = pointmark(pp[1]) - shift;
30399 out->o2facelist[o2index++] = pointmark(pp[2]) - shift;
30402 emlist[facenumber - in->firstnumber] = marker;
30404 if (b->neighout > 1) {
30405 out->face2tetlist[(facenumber - in->firstnumber) * 2] = neigh1;
30406 out->face2tetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
30412 tface.tet = tetrahedrontraverse();
30416 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30420 if (b->neighout > 1) {
30423 strcpy(facefilename, b->outfilename);
30424 strcat(facefilename,
".t2f");
30428 printf(
"Writing %s.\n", facefilename);
30430 printf(
"Writing tetrahedron-to-face map.\n");
30434 outfile = fopen(facefilename,
"w");
30435 for (tidx = 0; tidx < ntets; tidx++) {
30437 fprintf(outfile,
"%4d %d %d %d %d\n", tidx + in->firstnumber,
30438 tet2facelist[index], tet2facelist[index+1],
30439 tet2facelist[index+2], tet2facelist[index+3]);
30442 delete [] tet2facelist;
30445 out->tet2facelist = tet2facelist;
30458 void tetgenmesh::outhullfaces(
tetgenio* out)
30460 FILE *outfile = NULL;
30461 char facefilename[FILENAMESIZE];
30463 point torg, tdest, tapex;
30465 int firstindex, shift;
30470 strcpy(facefilename, b->outfilename);
30471 strcat(facefilename,
".face");
30476 printf(
"Writing %s.\n", facefilename);
30478 printf(
"Writing faces.\n");
30483 outfile = fopen(facefilename,
"w");
30484 if (outfile == (FILE *) NULL) {
30485 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30486 terminatetetgen(
this, 1);
30488 fprintf(outfile,
"%ld 0\n", hullsize);
30491 out->trifacelist =
new int[hullsize * 3];
30492 if (out->trifacelist == (
int *) NULL) {
30493 printf(
"Error: Out of memory.\n");
30494 terminatetetgen(
this, 1);
30496 out->numberoftrifaces = hullsize;
30497 elist = out->trifacelist;
30502 firstindex = b->zeroindex ? 0 : in->firstnumber;
30504 if ((in->firstnumber == 1) && (firstindex == 0)) {
30508 tetrahedrons->traversalinit();
30509 hulltet.tet = alltetrahedrontraverse();
30510 facenumber = firstindex;
30511 while (hulltet.tet != (tetrahedron *) NULL) {
30512 if (ishulltet(hulltet)) {
30513 torg = (point) hulltet.tet[4];
30514 tdest = (point) hulltet.tet[5];
30515 tapex = (point) hulltet.tet[6];
30518 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30519 pointmark(torg) - shift, pointmark(tdest) - shift,
30520 pointmark(tapex) - shift);
30521 fprintf(outfile,
"\n");
30524 elist[index++] = pointmark(torg) - shift;
30525 elist[index++] = pointmark(tdest) - shift;
30526 elist[index++] = pointmark(tapex) - shift;
30530 hulltet.tet = alltetrahedrontraverse();
30534 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30550 void tetgenmesh::outsubfaces(
tetgenio* out)
30552 FILE *outfile = NULL;
30553 char facefilename[FILENAMESIZE];
30555 int *emlist = NULL;
30556 int index = 0, index1 = 0, index2 = 0;
30557 triface abuttingtet;
30559 point torg, tdest, tapex;
30561 int firstindex, shift;
30562 int neigh1 = 0, neigh2 = 0;
30567 point *extralist, pp[3] = {0,0,0};
30568 int highorderindex = 11;
30569 int o2index = 0, i;
30574 strcpy(facefilename, b->outfilename);
30575 strcat(facefilename,
".face");
30580 printf(
"Writing %s.\n", facefilename);
30582 printf(
"Writing faces.\n");
30587 outfile = fopen(facefilename,
"w");
30588 if (outfile == (FILE *) NULL) {
30589 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
30590 terminatetetgen(
this, 3);
30593 fprintf(outfile,
"%ld %d\n", subfaces->items, !b->nobound);
30596 out->trifacelist =
new int[subfaces->items * 3];
30597 if (out->trifacelist == (
int *) NULL) {
30598 terminatetetgen(
this, 1);
30600 if (b->order == 2) {
30601 out->o2facelist =
new int[subfaces->items * 3];
30605 out->trifacemarkerlist =
new int[subfaces->items];
30606 if (out->trifacemarkerlist == (
int *) NULL) {
30607 terminatetetgen(
this, 1);
30610 if (b->neighout > 1) {
30612 out->face2tetlist =
new int[subfaces->items * 2];
30613 if (out->face2tetlist == (
int *) NULL) {
30614 terminatetetgen(
this, 1);
30617 out->numberoftrifaces = subfaces->items;
30618 elist = out->trifacelist;
30619 emlist = out->trifacemarkerlist;
30623 firstindex = b->zeroindex ? 0 : in->firstnumber;
30625 if ((in->firstnumber == 1) && (firstindex == 0)) {
30629 subfaces->traversalinit();
30630 faceloop.sh = shellfacetraverse(subfaces);
30631 facenumber = firstindex;
30632 while (faceloop.sh != (shellface *) NULL) {
30633 stpivot(faceloop, abuttingtet);
30637 if (abuttingtet.tet != NULL) {
30638 if (ishulltet(abuttingtet)) {
30639 fsymself(abuttingtet);
30642 if (abuttingtet.tet != NULL) {
30643 torg = org(abuttingtet);
30644 tdest = dest(abuttingtet);
30645 tapex = apex(abuttingtet);
30646 if (b->order == 2) {
30648 extralist = (point *) (abuttingtet.tet[highorderindex]);
30649 workface = abuttingtet;
30650 for (i = 0; i < 3; i++) {
30651 pp[i] = extralist[ver2edge[workface.ver]];
30652 enextself(workface);
30657 torg = sorg(faceloop);
30658 tdest = sdest(faceloop);
30659 tapex = sapex(faceloop);
30660 if (b->order == 2) {
30668 marker = shellmark(faceloop);
30670 if (b->neighout > 1) {
30674 stpivot(faceloop, abuttingtet);
30675 if (abuttingtet.tet != NULL) {
30676 if (!ishulltet(abuttingtet)) {
30677 neigh1 = elemindex(abuttingtet.tet);
30679 fsymself(abuttingtet);
30680 if (!ishulltet(abuttingtet)) {
30681 neigh2 = elemindex(abuttingtet.tet);
30686 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
30687 pointmark(torg) - shift, pointmark(tdest) - shift,
30688 pointmark(tapex) - shift);
30689 if (b->order == 2) {
30690 fprintf(outfile,
" %4d %4d %4d", pointmark(pp[0]) - shift,
30691 pointmark(pp[1]) - shift, pointmark(pp[2]) - shift);
30694 fprintf(outfile,
" %d", marker);
30696 if (b->neighout > 1) {
30697 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
30699 fprintf(outfile,
"\n");
30702 elist[index++] = pointmark(torg) - shift;
30703 elist[index++] = pointmark(tdest) - shift;
30704 elist[index++] = pointmark(tapex) - shift;
30705 if (b->order == 2) {
30706 out->o2facelist[o2index++] = pointmark(pp[0]) - shift;
30707 out->o2facelist[o2index++] = pointmark(pp[1]) - shift;
30708 out->o2facelist[o2index++] = pointmark(pp[2]) - shift;
30711 emlist[index1++] = marker;
30713 if (b->neighout > 1) {
30714 out->face2tetlist[index2++] = neigh1;
30715 out->face2tetlist[index2++] = neigh2;
30719 faceloop.sh = shellfacetraverse(subfaces);
30723 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30737 void tetgenmesh::outedges(
tetgenio* out)
30739 FILE *outfile = NULL;
30740 char edgefilename[FILENAMESIZE];
30741 triface tetloop, worktet, spintet;
30745 int firstindex, shift;
30746 int edgenumber, marker;
30747 int index = 0, index1 = 0, index2 = 0;
30752 point *extralist, pp = NULL;
30753 int highorderindex = 11;
30757 int *tet2edgelist = NULL;
30761 strcpy(edgefilename, b->outfilename);
30762 strcat(edgefilename,
".edge");
30767 printf(
"Writing %s.\n", edgefilename);
30769 printf(
"Writing edges.\n");
30773 if (meshedges == 0l) {
30779 long tsize = tetrahedrons->items - hullsize;
30780 long fsize = (tsize * 4l + hullsize) / 2l;
30781 long vsize = points->items - dupverts - unuverts;
30782 if (b->weighted) vsize -= nonregularcount;
30783 meshedges = vsize + fsize - tsize - 1;
30786 meshhulledges = 0l;
30789 outfile = fopen(edgefilename,
"w");
30790 if (outfile == (FILE *) NULL) {
30791 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
30792 terminatetetgen(
this, 1);
30795 fprintf(outfile,
"%ld %d\n", meshedges, !b->nobound);
30798 out->numberofedges = meshedges;
30799 out->edgelist =
new int[meshedges * 2];
30800 if (out->edgelist == (
int *) NULL) {
30801 printf(
"Error: Out of memory.\n");
30802 terminatetetgen(
this, 1);
30804 if (b->order == 2) {
30805 out->o2edgelist =
new int[meshedges];
30808 out->edgemarkerlist =
new int[meshedges];
30810 if (b->neighout > 1) {
30811 out->edge2tetlist =
new int[meshedges];
30815 if (b->neighout > 1) {
30817 long tsize = tetrahedrons->items - hullsize;
30818 tet2edgelist =
new int[tsize * 6];
30822 firstindex = b->zeroindex ? 0 : in->firstnumber;
30824 if ((in->firstnumber == 1) && (firstindex == 0)) {
30828 tetrahedrons->traversalinit();
30829 tetloop.tet = tetrahedrontraverse();
30830 edgenumber = firstindex;
30831 while (tetloop.tet != (tetrahedron *) NULL) {
30833 worktet.tet = tetloop.tet;
30834 for (i = 0; i < 6; i++) {
30835 worktet.ver = edge2ver[i];
30837 fnext(worktet, spintet);
30839 if (!ishulltet(spintet)) {
30840 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
30844 fnextself(spintet);
30845 }
while (spintet.tet != worktet.tet);
30846 if (spintet.tet == worktet.tet) {
30848 if (ishulledge) meshhulledges++;
30849 torg = org(worktet);
30850 tdest = dest(worktet);
30851 if (b->order == 2) {
30853 extralist = (point *) worktet.tet[highorderindex];
30854 pp = extralist[ver2edge[worktet.ver]];
30857 fprintf(outfile,
"%5d %4d %4d", edgenumber,
30858 pointmark(torg) - shift, pointmark(tdest) - shift);
30859 if (b->order == 2) {
30860 fprintf(outfile,
" %4d", pointmark(pp) - shift);
30864 out->edgelist[index++] = pointmark(torg) - shift;
30865 out->edgelist[index++] = pointmark(tdest) - shift;
30866 if (b->order == 2) {
30867 out->o2edgelist[o2index++] = pointmark(pp) - shift;
30871 if (b->plc || b->refine) {
30873 tsspivot1(worktet, checkseg);
30874 if (checkseg.sh != NULL) {
30875 marker = shellmark(checkseg);
30881 marker = ishulledge ? 1 : 0;
30884 fprintf(outfile,
" %d", marker);
30886 out->edgemarkerlist[index1++] = marker;
30889 if (b->neighout > 1) {
30891 fprintf(outfile,
" %d", elemindex(tetloop.tet));
30893 out->edge2tetlist[index2++] = elemindex(tetloop.tet);
30898 if (!ishulltet(spintet)) {
30899 tidx = elemindex(spintet.tet) - firstindex;
30900 tet2edgelist[tidx * 6 + ver2edge[spintet.ver]] = edgenumber;
30902 fnextself(spintet);
30903 if (spintet.tet == worktet.tet)
break;
30907 fprintf(outfile,
"\n");
30912 tetloop.tet = tetrahedrontraverse();
30916 fprintf(outfile,
"# Generated by %s\n", b->commandline);
30920 if (b->neighout > 1) {
30921 long tsize = tetrahedrons->items - hullsize;
30925 long fsize = (tsize * 4l + hullsize) / 2l;
30926 int *face2edgelist =
new int[fsize * 3];
30928 tetrahedrons->traversalinit();
30929 tetloop.tet = tetrahedrontraverse();
30930 int facenumber = 0;
30931 while (tetloop.tet != (tetrahedron *) NULL) {
30932 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
30933 fsym(tetloop, spintet);
30934 if (ishulltet(spintet) ||
30935 (elemindex(tetloop.tet) < elemindex(spintet.tet))) {
30939 tidx = elemindex(tetloop.tet) - firstindex;
30941 for (i = 0; i < 3; i++) {
30942 enextself(worktet);
30943 int eidx = tet2edgelist[tidx * 6 + ver2edge[worktet.ver]];
30944 face2edgelist[facenumber * 3 + i] = eidx;
30949 tetloop.tet = tetrahedrontraverse();
30954 strcpy(edgefilename, b->outfilename);
30955 strcat(edgefilename,
".f2e");
30959 printf(
"Writing %s.\n", edgefilename);
30961 printf(
"Writing face-to-edge map.\n");
30965 outfile = fopen(edgefilename,
"w");
30966 for (tidx = 0; tidx < fsize; tidx++) {
30968 fprintf(outfile,
"%4d %d %d %d\n", tidx + in->firstnumber,
30969 face2edgelist[i], face2edgelist[i+1], face2edgelist[i+2]);
30972 delete [] face2edgelist;
30975 out->face2edgelist = face2edgelist;
30981 strcpy(edgefilename, b->outfilename);
30982 strcat(edgefilename,
".t2e");
30986 printf(
"Writing %s.\n", edgefilename);
30988 printf(
"Writing tetrahedron-to-edge map.\n");
30992 outfile = fopen(edgefilename,
"w");
30993 for (tidx = 0; tidx < tsize; tidx++) {
30995 fprintf(outfile,
"%4d %d %d %d %d %d %d\n", tidx + in->firstnumber,
30996 tet2edgelist[i], tet2edgelist[i+1], tet2edgelist[i+2],
30997 tet2edgelist[i+3], tet2edgelist[i+4], tet2edgelist[i+5]);
31000 delete [] tet2edgelist;
31003 out->tet2edgelist = tet2edgelist;
31014 void tetgenmesh::outsubsegments(
tetgenio* out)
31016 FILE *outfile = NULL;
31017 char edgefilename[FILENAMESIZE];
31022 int firstindex, shift;
31027 triface workface, spintet;
31028 point *extralist, pp = NULL;
31029 int highorderindex = 11;
31039 strcpy(edgefilename, b->outfilename);
31040 strcat(edgefilename,
".edge");
31045 printf(
"Writing %s.\n", edgefilename);
31047 printf(
"Writing edges.\n");
31052 outfile = fopen(edgefilename,
"w");
31053 if (outfile == (FILE *) NULL) {
31054 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
31055 terminatetetgen(
this, 3);
31058 fprintf(outfile,
"%ld 1\n", subsegs->items);
31061 out->edgelist =
new int[subsegs->items * (b->order == 1 ? 2 : 3)];
31062 if (out->edgelist == (
int *) NULL) {
31063 terminatetetgen(
this, 1);
31065 if (b->order == 2) {
31066 out->o2edgelist =
new int[subsegs->items];
31068 out->edgemarkerlist =
new int[subsegs->items];
31069 if (out->edgemarkerlist == (
int *) NULL) {
31070 terminatetetgen(
this, 1);
31072 if (b->neighout > 1) {
31073 out->edge2tetlist =
new int[subsegs->items];
31075 out->numberofedges = subsegs->items;
31076 elist = out->edgelist;
31080 firstindex = b->zeroindex ? 0 : in->firstnumber;
31082 if ((in->firstnumber == 1) && (firstindex == 0)) {
31088 subsegs->traversalinit();
31089 edgeloop.sh = shellfacetraverse(subsegs);
31090 edgenumber = firstindex;
31091 while (edgeloop.sh != (shellface *) NULL) {
31092 torg = sorg(edgeloop);
31093 tdest = sdest(edgeloop);
31094 if ((b->order == 2) || (b->neighout > 1)) {
31095 sstpivot1(edgeloop, workface);
31096 if (workface.tet != NULL) {
31098 if (ishulltet(workface)) {
31099 spintet = workface;
31101 fnextself(spintet);
31102 if (!ishulltet(spintet))
break;
31103 if (spintet.tet == workface.tet)
break;
31105 workface = spintet;
31109 if (b->order == 2) {
31111 if (workface.tet != NULL) {
31112 extralist = (point *) workface.tet[highorderindex];
31113 pp = extralist[ver2edge[workface.ver]];
31118 if (b->neighout > 1) {
31119 if (workface.tet != NULL) {
31120 neigh = elemindex(workface.tet);
31125 marker = shellmark(edgeloop);
31130 fprintf(outfile,
"%5d %4d %4d", edgenumber,
31131 pointmark(torg) - shift, pointmark(tdest) - shift);
31132 if (b->order == 2) {
31133 fprintf(outfile,
" %4d", pointmark(pp) - shift);
31135 fprintf(outfile,
" %d", marker);
31136 if (b->neighout > 1) {
31137 fprintf(outfile,
" %4d", neigh);
31139 fprintf(outfile,
"\n");
31142 elist[index++] = pointmark(torg) - shift;
31143 elist[index++] = pointmark(tdest) - shift;
31144 if (b->order == 2) {
31145 out->o2edgelist[o2index++] = pointmark(pp) - shift;
31147 out->edgemarkerlist[i++] = marker;
31148 if (b->neighout > 1) {
31149 out->edge2tetlist[index2++] = neigh;
31153 edgeloop.sh = shellfacetraverse(subsegs);
31157 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31168 void tetgenmesh::outneighbors(
tetgenio* out)
31170 FILE *outfile = NULL;
31171 char neighborfilename[FILENAMESIZE];
31174 triface tetloop, tetsym;
31181 strcpy(neighborfilename, b->outfilename);
31182 strcat(neighborfilename,
".neigh");
31187 printf(
"Writing %s.\n", neighborfilename);
31189 printf(
"Writing neighbors.\n");
31193 ntets = tetrahedrons->items - hullsize;
31196 outfile = fopen(neighborfilename,
"w");
31197 if (outfile == (FILE *) NULL) {
31198 printf(
"File I/O Error: Cannot create file %s.\n", neighborfilename);
31199 terminatetetgen(
this, 1);
31202 fprintf(outfile,
"%ld %d\n", ntets, 4);
31205 out->neighborlist =
new int[ntets * 4];
31206 if (out->neighborlist == (
int *) NULL) {
31207 printf(
"Error: Out of memory.\n");
31208 terminatetetgen(
this, 1);
31210 nlist = out->neighborlist;
31214 firstindex = b->zeroindex ? 0 : in->firstnumber;
31216 tetrahedrons->traversalinit();
31217 tetloop.tet = tetrahedrontraverse();
31218 elementnumber = firstindex;
31219 while (tetloop.tet != (tetrahedron *) NULL) {
31220 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
31221 fsym(tetloop, tetsym);
31222 if (!ishulltet(tetsym)) {
31223 neighbori[tetloop.ver] = elemindex(tetsym.tet);
31225 neighbori[tetloop.ver] = -1;
31230 fprintf(outfile,
"%4d %4d %4d %4d %4d\n", elementnumber,
31231 neighbori[0], neighbori[1], neighbori[2], neighbori[3]);
31233 nlist[index++] = neighbori[0];
31234 nlist[index++] = neighbori[1];
31235 nlist[index++] = neighbori[2];
31236 nlist[index++] = neighbori[3];
31238 tetloop.tet = tetrahedrontraverse();
31243 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31269 void tetgenmesh::outvoronoi(
tetgenio* out)
31271 FILE *outfile = NULL;
31272 char outfilename[FILENAMESIZE];
31275 arraypool *tetlist, *ptlist;
31276 triface tetloop, worktet, spintet, firsttet;
31277 point pt[4], ploop, neipt;
31278 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
31279 long ntets, faces, edges;
31280 int *indexarray, *fidxs, *eidxs;
31282 int vpointcount, vedgecount, vfacecount, tcount;
31283 int ishullvert, ishullface;
31284 int index, shift, end1, end2;
31291 strcpy(outfilename, b->outfilename);
31292 strcat(outfilename,
".v.node");
31297 printf(
"Writing %s.\n", outfilename);
31299 printf(
"Writing Voronoi vertices.\n");
31304 shift = (b->zeroindex ? 0 : in->firstnumber);
31311 indexarray =
new int[tetrahedrons->items * 10];
31316 tetrahedrons->traversalinit();
31317 tetloop.tet = alltetrahedrontraverse();
31318 while (tetloop.tet != NULL) {
31319 tetloop.tet[11] = (tetrahedron) &(indexarray[i * 10]);
31321 tetloop.tet = alltetrahedrontraverse();
31325 ntets = tetrahedrons->items - hullsize;
31327 faces = (4l * ntets + hullsize) / 2l;
31329 long vsize = points->items - dupverts - unuverts;
31330 if (b->weighted) vsize -= nonregularcount;
31332 edges = vsize + faces - ntets - 1;
31334 if (meshedges == 0l) {
31341 outfile = fopen(outfilename,
"w");
31342 if (outfile == (FILE *) NULL) {
31343 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31344 terminatetetgen(
this, 3);
31347 fprintf(outfile,
"%ld 3 0 0\n", ntets);
31350 out->numberofvpoints = (int) ntets;
31351 out->vpointlist =
new REAL[out->numberofvpoints * 3];
31352 if (out->vpointlist == (REAL *) NULL) {
31353 terminatetetgen(
this, 1);
31358 tetrahedrons->traversalinit();
31359 tetloop.tet = tetrahedrontraverse();
31362 while (tetloop.tet != (tetrahedron *) NULL) {
31363 for (i = 0; i < 4; i++) {
31364 pt[i] = (point) tetloop.tet[4 + i];
31365 setpoint2tet(pt[i], encode(tetloop));
31368 orthosphere(pt[0], pt[1], pt[2], pt[3], pt[0][3], pt[1][3], pt[2][3],
31369 pt[3][3], ccent, NULL);
31371 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
31374 fprintf(outfile,
"%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
31375 ccent[0], ccent[1], ccent[2]);
31377 out->vpointlist[index++] = ccent[0];
31378 out->vpointlist[index++] = ccent[1];
31379 out->vpointlist[index++] = ccent[2];
31381 setelemindex(tetloop.tet, vpointcount);
31383 tetloop.tet = tetrahedrontraverse();
31387 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31393 strcpy(outfilename, b->outfilename);
31394 strcat(outfilename,
".v.edge");
31399 printf(
"Writing %s.\n", outfilename);
31401 printf(
"Writing Voronoi edges.\n");
31406 outfile = fopen(outfilename,
"w");
31407 if (outfile == (FILE *) NULL) {
31408 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31409 terminatetetgen(
this, 3);
31412 fprintf(outfile,
"%ld 0\n", faces);
31415 out->numberofvedges = (int) faces;
31420 tetrahedrons->traversalinit();
31421 tetloop.tet = tetrahedrontraverse();
31424 while (tetloop.tet != (tetrahedron *) NULL) {
31428 end1 = elemindex(tetloop.tet);
31429 for (tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
31430 fsym(tetloop, worktet);
31431 if (ishulltet(worktet) ||
31432 (elemindex(tetloop.tet) < elemindex(worktet.tet))) {
31435 fprintf(outfile,
"%4d %4d", vedgecount + shift, end1 + shift);
31437 vedge = &(out->vedgelist[index++]);
31438 vedge->v1 = end1 + shift;
31440 if (!ishulltet(worktet)) {
31441 end2 = elemindex(worktet.tet);
31448 pt[0] = dest(worktet);
31449 pt[1] = org(worktet);
31450 pt[2] = apex(worktet);
31451 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
31452 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
31453 cross(vec1, vec2, infvec);
31455 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
31456 + infvec[2] * infvec[2]);
31457 if (L > 0)
for (j = 0; j < 3; j++) infvec[j] /= L;
31459 fprintf(outfile,
" -1");
31460 fprintf(outfile,
" %g %g %g\n", infvec[0], infvec[1], infvec[2]);
31463 vedge->vnormal[0] = infvec[0];
31464 vedge->vnormal[1] = infvec[1];
31465 vedge->vnormal[2] = infvec[2];
31469 fprintf(outfile,
" %4d\n", end2 + shift);
31471 vedge->v2 = end2 + shift;
31472 vedge->vnormal[0] = 0.0;
31473 vedge->vnormal[1] = 0.0;
31474 vedge->vnormal[2] = 0.0;
31478 fidxs = (
int *) (tetloop.tet[11]);
31479 fidxs[tetloop.ver] = vedgecount;
31480 fidxs = (
int *) (worktet.tet[11]);
31481 fidxs[worktet.ver & 3] = vedgecount;
31485 tetloop.tet = tetrahedrontraverse();
31489 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31495 strcpy(outfilename, b->outfilename);
31496 strcat(outfilename,
".v.face");
31501 printf(
"Writing %s.\n", outfilename);
31503 printf(
"Writing Voronoi faces.\n");
31508 outfile = fopen(outfilename,
"w");
31509 if (outfile == (FILE *) NULL) {
31510 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31511 terminatetetgen(
this, 3);
31514 fprintf(outfile,
"%ld 0\n", edges);
31516 out->numberofvfacets = edges;
31519 terminatetetgen(
this, 1);
31524 tetrahedrons->traversalinit();
31525 tetloop.tet = tetrahedrontraverse();
31527 while (tetloop.tet != (tetrahedron *) NULL) {
31531 worktet.tet = tetloop.tet;
31532 for (i = 0; i < 6; i++) {
31533 worktet.ver = edge2ver[i];
31538 firsttet = worktet;
31542 fnextself(spintet);
31543 if (spintet.tet == worktet.tet)
break;
31544 if (!ishulltet(spintet)) {
31545 if (elemindex(spintet.tet) < elemindex(worktet.tet))
break;
31548 if (apex(spintet) == dummypoint) {
31550 fnext(spintet, firsttet);
31554 if (spintet.tet == worktet.tet) {
31556 pt[0] = org(worktet);
31557 pt[1] = dest(worktet);
31558 end1 = pointmark(pt[0]) - in->firstnumber;
31559 end2 = pointmark(pt[1]) - in->firstnumber;
31561 fprintf(outfile,
"%4d %4d %4d %-2d ", vfacecount + shift,
31562 end1 + shift, end2 + shift, tcount);
31564 vfacet = &(out->vfacetlist[vfacecount]);
31565 vfacet->c1 = end1 + shift;
31566 vfacet->c2 = end2 + shift;
31567 vfacet->elist =
new int[tcount + 1];
31568 vfacet->elist[0] = tcount;
31572 spintet = firsttet;
31574 fidxs = (
int *) (spintet.tet[11]);
31575 if (apex(spintet) != dummypoint) {
31576 vedgecount = fidxs[spintet.ver & 3];
31582 fprintf(outfile,
" %d", !ishullface ? (vedgecount + shift) : -1);
31584 vfacet->elist[index++] = !ishullface ? (vedgecount + shift) : -1;
31587 eidxs = &(fidxs[4]);
31588 eidxs[ver2edge[spintet.ver]] = vfacecount;
31590 fnextself(spintet);
31591 if (spintet.tet == firsttet.tet)
break;
31594 fprintf(outfile,
"\n");
31599 tetloop.tet = tetrahedrontraverse();
31603 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31609 strcpy(outfilename, b->outfilename);
31610 strcat(outfilename,
".v.cell");
31615 printf(
"Writing %s.\n", outfilename);
31617 printf(
"Writing Voronoi cells.\n");
31622 outfile = fopen(outfilename,
"w");
31623 if (outfile == (FILE *) NULL) {
31624 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
31625 terminatetetgen(
this, 3);
31628 fprintf(outfile,
"%ld\n", points->items - unuverts - dupverts);
31630 out->numberofvcells = points->items - unuverts - dupverts;
31631 out->vcelllist =
new int*[out->numberofvcells];
31632 if (out->vcelllist == (
int **) NULL) {
31633 terminatetetgen(
this, 1);
31638 tetlist = cavetetlist;
31639 ptlist = cavetetvertlist;
31640 points->traversalinit();
31641 ploop = pointtraverse();
31643 while (ploop != (point) NULL) {
31644 if ((pointtype(ploop) != UNUSEDVERTEX) &&
31645 (pointtype(ploop) != DUPLICATEDVERTEX) &&
31646 (pointtype(ploop) != NREGULARVERTEX)) {
31647 getvertexstar(1, ploop, tetlist, ptlist, NULL);
31650 for (i = 0; i < ptlist->objects; i++) {
31651 neipt = * (point *) fastlookup(ptlist, i);
31652 if (neipt != dummypoint) {
31658 tcount = (int) ptlist->objects;
31660 fprintf(outfile,
"%4d %-2d ", vpointcount + shift, tcount);
31662 arraysize = tcount;
31664 out->vcelllist[vpointcount] =
vertarray;
31669 for (i = 0; i < tetlist->objects; i++) {
31670 worktet = * (triface *) fastlookup(tetlist, i);
31672 for (j = 0; j < 3; j++) {
31673 neipt = org(worktet);
31675 if (neipt != dummypoint) {
31676 if (pinfected(neipt)) {
31680 esym(worktet, spintet);
31681 enextself(spintet);
31683 eidxs = (
int *) spintet.tet[11];
31684 vfacecount = eidxs[4 + ver2edge[spintet.ver]];
31686 fprintf(outfile,
" %d", vfacecount + shift);
31688 vertarray[index++] = vfacecount + shift;
31692 enextself(worktet);
31698 fprintf(outfile,
" -1");
31704 fprintf(outfile,
"\n");
31706 tetlist->restart();
31710 ploop = pointtraverse();
31714 delete [] indexarray;
31717 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31733 void tetgenmesh::outsmesh(
char* smfilename)
31736 char nodfilename[FILENAMESIZE];
31737 char smefilename[FILENAMESIZE];
31740 int firstindex, shift;
31745 if (smfilename != (
char *) NULL && smfilename[0] !=
'\0') {
31746 strcpy(smefilename, smfilename);
31747 }
else if (b->outfilename[0] !=
'\0') {
31748 strcpy(smefilename, b->outfilename);
31750 strcpy(smefilename,
"unnamed");
31752 strcpy(nodfilename, smefilename);
31753 strcat(smefilename,
".smesh");
31754 strcat(nodfilename,
".node");
31757 printf(
"Writing %s.\n", smefilename);
31759 outfile = fopen(smefilename,
"w");
31760 if (outfile == (FILE *) NULL) {
31761 printf(
"File I/O Error: Cannot create file %s.\n", smefilename);
31766 firstindex = b->zeroindex ? 0 : in->firstnumber;
31768 if ((in->firstnumber == 1) && (firstindex == 0)) {
31772 fprintf(outfile,
"# %s. TetGen's input file.\n", smefilename);
31773 fprintf(outfile,
"\n# part 1: node list.\n");
31774 fprintf(outfile,
"0 3 0 0 # nodes are found in %s.\n", nodfilename);
31777 bmark = !b->nobound && (in->facetmarkerlist || in->trifacemarkerlist);
31779 fprintf(outfile,
"\n# part 2: facet list.\n");
31781 fprintf(outfile,
"%ld %d\n", subfaces->items, bmark);
31783 subfaces->traversalinit();
31784 faceloop.sh = shellfacetraverse(subfaces);
31785 while (faceloop.sh != (shellface *) NULL) {
31786 p1 = sorg(faceloop);
31787 p2 = sdest(faceloop);
31788 p3 = sapex(faceloop);
31790 marker = shellmark(faceloop);
31792 fprintf(outfile,
"3 %4d %4d %4d", pointmark(p1) - shift,
31793 pointmark(p2) - shift, pointmark(p3) - shift);
31795 fprintf(outfile,
" %d", marker);
31797 fprintf(outfile,
"\n");
31798 faceloop.sh = shellfacetraverse(subfaces);
31802 fprintf(outfile,
"\n# part 3: hole list.\n");
31803 fprintf(outfile,
"%d\n", in->numberofholes);
31804 for (i = 0; i < in->numberofholes; i++) {
31805 fprintf(outfile,
"%d %g %g %g\n", i + in->firstnumber,
31806 in->holelist[i * 3], in->holelist[i * 3 + 1],
31807 in->holelist[i * 3 + 2]);
31811 fprintf(outfile,
"\n# part 4: region list.\n");
31812 fprintf(outfile,
"%d\n", in->numberofregions);
31813 for (i = 0; i < in->numberofregions; i++) {
31814 fprintf(outfile,
"%d %g %g %g %d %g\n", i + in->firstnumber,
31815 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
31816 in->regionlist[i * 5 + 2], (
int) in->regionlist[i * 5 + 3],
31817 in->regionlist[i * 5 + 4]);
31820 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31835 void tetgenmesh::outmesh2medit(
char* mfilename)
31838 char mefilename[FILENAMESIZE];
31839 tetrahedron* tetptr;
31840 triface tface, tsymface;
31841 face segloop, checkmark;
31842 point ptloop, p1, p2, p3, p4;
31848 if (mfilename != (
char *) NULL && mfilename[0] !=
'\0') {
31849 strcpy(mefilename, mfilename);
31850 }
else if (b->outfilename[0] !=
'\0') {
31851 strcpy(mefilename, b->outfilename);
31853 strcpy(mefilename,
"unnamed");
31855 strcat(mefilename,
".mesh");
31858 printf(
"Writing %s.\n", mefilename);
31860 outfile = fopen(mefilename,
"w");
31861 if (outfile == (FILE *) NULL) {
31862 printf(
"File I/O Error: Cannot create file %s.\n", mefilename);
31866 fprintf(outfile,
"MeshVersionFormatted 1\n");
31867 fprintf(outfile,
"\n");
31868 fprintf(outfile,
"Dimension\n");
31869 fprintf(outfile,
"3\n");
31870 fprintf(outfile,
"\n");
31872 fprintf(outfile,
"\n# Set of mesh vertices\n");
31873 fprintf(outfile,
"Vertices\n");
31874 fprintf(outfile,
"%ld\n", points->items);
31876 points->traversalinit();
31877 ptloop = pointtraverse();
31879 while (ptloop != (point) NULL) {
31881 fprintf(outfile,
"%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
31882 if (in->numberofpointattributes > 0) {
31884 fprintf(outfile,
" %.17g\n", ptloop[3]);
31886 fprintf(outfile,
" 0\n");
31888 setpointmark(ptloop, pointnumber);
31889 ptloop = pointtraverse();
31894 ntets = tetrahedrons->items - hullsize;
31895 faces = (ntets * 4l + hullsize) / 2l;
31897 fprintf(outfile,
"\n# Set of Triangles\n");
31898 fprintf(outfile,
"Triangles\n");
31899 fprintf(outfile,
"%ld\n", faces);
31901 tetrahedrons->traversalinit();
31902 tface.tet = tetrahedrontraverse();
31903 while (tface.tet != (tetrahedron *) NULL) {
31904 for (tface.ver = 0; tface.ver < 4; tface.ver ++) {
31905 fsym(tface, tsymface);
31906 if (ishulltet(tsymface) ||
31907 (elemindex(tface.tet) < elemindex(tsymface.tet))) {
31911 fprintf(outfile,
"%5d %5d %5d",
31912 pointmark(p1), pointmark(p2), pointmark(p3));
31914 tspivot(tface, checkmark);
31915 if (checkmark.sh == NULL) {
31918 marker = shellmark(checkmark);
31920 fprintf(outfile,
" %d\n", marker);
31923 tface.tet = tetrahedrontraverse();
31926 fprintf(outfile,
"\n# Set of Tetrahedra\n");
31927 fprintf(outfile,
"Tetrahedra\n");
31928 fprintf(outfile,
"%ld\n", ntets);
31930 tetrahedrons->traversalinit();
31931 tetptr = tetrahedrontraverse();
31932 while (tetptr != (tetrahedron *) NULL) {
31933 if (!b->reversetetori) {
31934 p1 = (point) tetptr[4];
31935 p2 = (point) tetptr[5];
31937 p1 = (point) tetptr[5];
31938 p2 = (point) tetptr[4];
31940 p3 = (point) tetptr[6];
31941 p4 = (point) tetptr[7];
31942 fprintf(outfile,
"%5d %5d %5d %5d",
31943 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
31944 if (numelemattrib > 0) {
31945 fprintf(outfile,
" %.17g", elemattribute(tetptr, 0));
31947 fprintf(outfile,
" 0");
31949 fprintf(outfile,
"\n");
31950 tetptr = tetrahedrontraverse();
31953 fprintf(outfile,
"\nCorners\n");
31954 fprintf(outfile,
"%d\n", in->numberofpoints);
31956 for (i = 0; i < in->numberofpoints; i++) {
31957 fprintf(outfile,
"%4d\n", i + 1);
31960 if (b->plc || b->refine) {
31961 fprintf(outfile,
"\nEdges\n");
31962 fprintf(outfile,
"%ld\n", subsegs->items);
31964 subsegs->traversalinit();
31965 segloop.sh = shellfacetraverse(subsegs);
31966 while (segloop.sh != (shellface *) NULL) {
31967 p1 = sorg(segloop);
31968 p2 = sdest(segloop);
31969 fprintf(outfile,
"%5d %5d", pointmark(p1), pointmark(p2));
31970 marker = shellmark(segloop);
31971 fprintf(outfile,
" %d\n", marker);
31972 segloop.sh = shellfacetraverse(subsegs);
31976 fprintf(outfile,
"\nEnd\n");
31992 void tetgenmesh::outmesh2vtk(
char* ofilename)
31995 char vtkfilename[FILENAMESIZE];
31996 point pointloop, p1, p2, p3, p4;
31999 int n1, n2, n3, n4;
32003 if (b->order == 2) {
32004 printf(
" Write VTK not implemented for order 2 elements \n");
32008 int NEL = tetrahedrons->items - hullsize;
32009 int NN = points->items;
32011 if (ofilename != (
char *) NULL && ofilename[0] !=
'\0') {
32012 strcpy(vtkfilename, ofilename);
32013 }
else if (b->outfilename[0] !=
'\0') {
32014 strcpy(vtkfilename, b->outfilename);
32016 strcpy(vtkfilename,
"unnamed");
32018 strcat(vtkfilename,
".vtk");
32021 printf(
"Writing %s.\n", vtkfilename);
32023 outfile = fopen(vtkfilename,
"w");
32024 if (outfile == (FILE *) NULL) {
32025 printf(
"File I/O Error: Cannot create file %s.\n", vtkfilename);
32032 fprintf(outfile,
"# vtk DataFile Version 2.0\n");
32033 fprintf(outfile,
"Unstructured Grid\n");
32034 fprintf(outfile,
"ASCII\n");
32035 fprintf(outfile,
"DATASET UNSTRUCTURED_GRID\n");
32036 fprintf(outfile,
"POINTS %d double\n", NN);
32038 points->traversalinit();
32039 pointloop = pointtraverse();
32040 for(
int id=0;
id<NN && pointloop != (point) NULL;
id++){
32044 fprintf(outfile,
"%.17g %.17g %.17g\n", x, y, z);
32045 pointloop = pointtraverse();
32047 fprintf(outfile,
"\n");
32049 fprintf(outfile,
"CELLS %d %d\n", NEL, NEL*(4+1));
32052 tetrahedrons->traversalinit();
32053 tptr = tetrahedrontraverse();
32055 while (tptr != (tetrahedron *) NULL) {
32056 if (!b->reversetetori) {
32057 p1 = (point) tptr[4];
32058 p2 = (point) tptr[5];
32060 p1 = (point) tptr[5];
32061 p2 = (point) tptr[4];
32063 p3 = (point) tptr[6];
32064 p4 = (point) tptr[7];
32065 n1 = pointmark(p1) - in->firstnumber;
32066 n2 = pointmark(p2) - in->firstnumber;
32067 n3 = pointmark(p3) - in->firstnumber;
32068 n4 = pointmark(p4) - in->firstnumber;
32069 fprintf(outfile,
"%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
32070 tptr = tetrahedrontraverse();
32072 fprintf(outfile,
"\n");
32074 fprintf(outfile,
"CELL_TYPES %d\n", NEL);
32075 for(
int tid=0; tid<NEL; tid++){
32076 fprintf(outfile,
"%d\n", celltype);
32078 fprintf(outfile,
"\n");
32080 if (numelemattrib > 0) {
32082 fprintf(outfile,
"CELL_DATA %d\n", NEL);
32083 fprintf(outfile,
"SCALARS cell_scalars int 1\n");
32084 fprintf(outfile,
"LOOKUP_TABLE default\n");
32085 tetrahedrons->traversalinit();
32086 tptr = tetrahedrontraverse();
32087 while (tptr != (tetrahedron *) NULL) {
32088 fprintf(outfile,
"%d\n", (
int) elemattribute(tptr, numelemattrib - 1));
32089 tptr = tetrahedrontraverse();
32091 fprintf(outfile,
"\n");
32135 clock_t tv[12], ts[5];
32136 REAL cps = (REAL) CLOCKS_PER_SEC;
32144 if (b->metric && bgmin && (bgmin->numberofpoints > 0)) {
32150 m.initializepools();
32153 exactinit(b->verbose, b->noexact, b->nostaticfilter,
32154 m.xmax - m.xmin, m.ymax - m.ymin, m.zmax - m.zmin);
32159 m.reconstructmesh();
32161 m.incrementaldelaunay(ts[0]);
32168 printf(
"Mesh reconstruction seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps);
32170 printf(
"Delaunay seconds: %g\n", ((REAL)(tv[2]-tv[1])) / cps);
32172 printf(
" Point sorting seconds: %g\n", ((REAL)(ts[0]-tv[1])) / cps);
32178 if (b->plc && !b->refine) {
32184 printf(
"Surface mesh seconds: %g\n", ((REAL)(ts[0]-tv[2])) / cps);
32188 m.detectinterfaces();
32193 printf(
"Self-intersection seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps);
32197 if (m.subfaces->items > 0l) {
32199 m.outsubfaces(out);
32209 if ((b->metric) && (m.bgm != NULL)) {
32210 m.bgm->initializepools();
32211 m.bgm->transfernodes();
32212 m.bgm->reconstructmesh();
32217 printf(
"Background mesh reconstruct seconds: %g\n",
32218 ((REAL)(ts[0] - tv[3])) / cps);
32222 m.interpolatemeshsize();
32227 printf(
"Size interpolating seconds: %g\n",((REAL)(ts[1]-ts[0])) / cps);
32234 if (b->plc && !b->refine) {
32236 m.recoverboundary(ts[0]);
32238 m.constraineddelaunay(ts[0]);
32245 printf(
"Boundary recovery ");
32247 printf(
"Constrained Delaunay ");
32249 printf(
"seconds: %g\n", ((REAL)(ts[1] - tv[4])) / cps);
32251 printf(
" Segment recovery seconds: %g\n",((REAL)(ts[0]-tv[4]))/ cps);
32252 printf(
" Facet recovery seconds: %g\n", ((REAL)(ts[1]-ts[0])) / cps);
32261 printf(
"Exterior tets removal seconds: %g\n",((REAL)(ts[2]-ts[1]))/cps);
32265 if (m.subvertstack->objects > 0l) {
32266 m.suppresssteinerpoints();
32271 printf(
"Steiner suppression seconds: %g\n",
32272 ((REAL)(ts[3]-ts[2]))/cps);
32281 m.meshcoarsening();
32288 printf(
"Mesh coarsening seconds: %g\n", ((REAL)(tv[6] - tv[5])) / cps);
32292 if ((b->plc && b->nobisect) || b->coarsen) {
32293 m.recoverdelaunay();
32299 if ((b->plc && b->nobisect) || b->coarsen) {
32300 printf(
"Delaunay recovery seconds: %g\n", ((REAL)(tv[7] - tv[6]))/cps);
32304 if ((b->plc || b->refine) && b->insertaddpoints) {
32305 if ((addin != NULL) && (addin->numberofpoints > 0)) {
32306 m.insertconstrainedpoints(addin);
32313 if ((b->plc || b->refine) && b->insertaddpoints) {
32314 if ((addin != NULL) && (addin->numberofpoints > 0)) {
32315 printf(
"Constrained points seconds: %g\n", ((REAL)(tv[8]-tv[7]))/cps);
32321 m.delaunayrefinement();
32328 printf(
"Refinement seconds: %g\n", ((REAL)(tv[9] - tv[8])) / cps);
32332 if ((b->plc || b->refine) && (b->optlevel > 0)) {
32339 if ((b->plc || b->refine) && (b->optlevel > 0)) {
32340 printf(
"Optimization seconds: %g\n", ((REAL)(tv[10] - tv[9])) / cps);
32345 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
32346 || (b->refine && (in->numberofcorners == 10)))) {
32350 if ((b->order == 2) && !b->convex) {
32359 out->firstnumber = in->firstnumber;
32360 out->mesh_dim = in->mesh_dim;
32363 if (b->nonodewritten || b->noiterationnum) {
32365 printf(
"NOT writing a .node file.\n");
32371 if (b->noelewritten) {
32373 printf(
"NOT writing an .ele file.\n");
32377 if (m.tetrahedrons->items > 0l) {
32378 m.outelements(out);
32382 if (b->nofacewritten) {
32384 printf(
"NOT writing an .face file.\n");
32388 if (m.tetrahedrons->items > 0l) {
32392 if (b->plc || b->refine) {
32393 if (m.subfaces->items > 0l) {
32394 m.outsubfaces(out);
32397 if (m.tetrahedrons->items > 0l) {
32398 m.outhullfaces(out);
32405 if (b->nofacewritten) {
32407 printf(
"NOT writing an .edge file.\n");
32413 if (b->plc || b->refine) {
32414 m.outsubsegments(out);
32419 if ((b->plc || b->refine) && b->metric) {
32423 if (!out && b->plc &&
32424 ((b->object == tetgenbehavior::OFF) ||
32425 (b->object == tetgenbehavior::PLY) ||
32426 (b->object == tetgenbehavior::STL))) {
32427 m.outsmesh(b->outfilename);
32430 if (!out && b->meditview) {
32431 m.outmesh2medit(b->outfilename);
32436 m.outmesh2vtk(b->outfilename);
32440 m.outneighbors(out);
32451 printf(
"\nOutput seconds: %g\n", ((REAL)(tv[11] - tv[10])) / cps);
32452 printf(
"Total running seconds: %g\n", ((REAL)(tv[11] - tv[0])) / cps);
32457 if (b->plc || b->refine) {
32461 if (b->docheck > 1) {
32480 int main(
int argc,
char *argv[])
32482 #else // with TETLIBRARY 32493 #endif // not TETLIBRARY 32503 if (!b.parse_commandline(argc, argv)) {
32504 terminatetetgen(NULL, 10);
32509 if (!in.load_tetmesh(b.infilename, (
int) b.object)) {
32510 terminatetetgen(NULL, 10);
32513 if (!in.load_plc(b.infilename, (
int) b.object)) {
32514 terminatetetgen(NULL, 10);
32517 if (b.insertaddpoints) {
32519 addin.load_node(b.addinfilename);
32523 bgmin.load_tetmesh(b.bgmeshfilename, (
int) b.object);
32526 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
32530 #else // with TETLIBRARY 32532 if (!b.parse_commandline(switches)) {
32533 terminatetetgen(NULL, 10);
32535 mptr=tetrahedralize(&b, in, out, addin, bgmin);
32538 #endif // not TETLIBRARY